001/* $Source: /cvsroot2/open/projects/WebARTS/ca/bc/webarts/tools/AutoUpdateApp.java,v $ 002 * $Revision: 1295 $ $Date: 2019-04-18 18:05:01 -0700 (Thu, 18 Apr 2019) $ $Locker: $ 003 * Copyright 2001-2002 (C) WebARTS Design. All rights reserved. 004 * 005 * This program is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU General Public License 007 * as published by the Free Software Foundation; either version 2 008 * of the License, or any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU General Public License for more details. 014 * 015 * You should have received a copy of the GNU General Public License 016 * along with this program; if not, write to the Free Software 017 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 018*/ 019/* 020Here is the revision log 021------------------------ 022$Log: AutoUpdateApp.java,v $ 023Revision 1.4 2002/10/22 08:59:36 tgutwin 024Many JavaDoc Comments changes. 025Removed the StreamGobbler class... it now lives on its own in tools. 026small change to the exec call. 027 028Revision 1.3 2001/08/04 18:54:49 tgutwin 029 030Added the ability to read properties file from a file in the current dir. 031There are 3 places this app now looks for the prop file 0321) in the jar in the curr dir 0332) in the jar that is found in the classpath 0343) in the prop file in the curr dir. 035 036 037*/ 038 039package ca.bc.webarts.tools; 040 041 042 043import java.io.BufferedReader; 044import java.io.File; 045import java.io.FileInputStream; 046import java.io.FileOutputStream; 047import java.io.FileNotFoundException; 048import java.io.IOException; 049import java.io.InputStream; 050import java.io.InputStreamReader; 051import java.io.ObjectOutputStream; 052import java.io.PrintStream; 053import java.lang.Runtime; 054import java.lang.Process; 055import java.lang.SecurityException; 056import java.lang.String; 057import java.util.jar.JarFile; 058import java.util.jar.JarEntry; 059import java.util.jar.JarInputStream; 060import java.net.HttpURLConnection; 061import java.net.MalformedURLException; 062import java.net.URL; 063import java.net.URLConnection; 064import java.util.Enumeration; 065import java.util.Properties; 066import java.util.StringTokenizer; 067import java.util.Vector; 068 069// not necessary but saves headaches later if classes move 070import ca.bc.webarts.tools.StreamGobbler; 071 072import ca.bc.webarts.widgets.Util; 073 074/** 075 * This is a self standing Java application that acts as a middleware 076 * application executor that lets you put this class and a properties file on a 077 * client and be able to execute anything you want and have it update the app 078 * automatically from a specified URL. 079 * A <A HREF="#runApp(java.util.Properties)">static method</A> is also 080 * available to access the functionality from within existing code. 081 * <P>It executes applications... both native or Java as 082 * specified in a Properties file that gets passed to it (via a filename on the 083 * commandline). All system output from the executed app is echoed to the 084 * System.out (both regular and error output). 085 * <P> Its main purpose is to provide a single entrypoint to 086 * execute applications that can be dynamically specified at runtime. This 087 * allows a single deployment of this class onto a client and then tell this 088 * class what to run and where to download an update from if needed. 089 * <p>If you want this class to have a the name of your app; just extend this 090 * class and name it what you want... like the JOggPlayeAutoUpdate.java file. 091 * <P><B><U>Features:</U></B><UL><LI>executes Java<SUP><SMALL>TM</SMALL></SUP> 092 * Class files 093 * <LI>executes Java<SUP><SMALL>TM</SMALL></SUP> Jar files 094 * <LI>executes native executable files 095 * <LI>automatically retrieves the required files at a specified URL 096 * <LI>automatically checks for newer updated files at a specified URL 097 * <LI>automatically downmloads/updates any required files 098 * <LI>can run as an application or from existing code via the 099 * <A HREF="#runApp(java.util.Properties)">static runApp method</A></UL> 100 * <P><B><U>Usage:</U></B><BR><code>java AutoUpdateApp</code> < 101 * <code>propertiesFilename</code>> OR<BR> 102 * <code>java -jar AutoUpdateApp.jar</code> 103 * <<code>propertiesFilename</code>><P> 104 * The <B>properties file</B> describes the app to 105 * execute. It has both required and optional entries as follows: 106 * <UL> 107 * <LI><B>Required Entries</B></LI> 108 * <UL> 109 * <LI><I><U>appType</U></I> - a String specifying the type of app that will 110 * be executed 111 * <BR>(NATIVE_APP = native; JAVA_APP = java; 112* APPLET_APP = applet; HTTPURL_APP = httpUrl) 113 * </LI> 114 * <LI><I><U>remoteAppURL</U></I> - a string specifying URL for the application 115 * to launch<BR> 116 * (for example: file://usr/bin/telnet.sh or file:/c:/winnt/wordpad.exe) 117 * </LI> 118 * </UL><BR> 119 * <LI><B>Optional Entries</B></LI> 120 * <UL><LI><I><U>remoteAppAutoDownload</U></I> - a string specifying 121 * the flag (boolean string value) that specifies if this app should query the 122 * download server (see property below) for updated app files.</LI> 123 * <LI><I><U>remoteAppDownloadURL</U></I> - a string specifying 124 * the URL of the download for the Remote Launch APP. If the filename portion 125 * of this URL does not match the filename portion of the remoteAppURL this app 126 * will assume it is an archive file (ie Jar file) that will be downloaded and 127 * will save it as a separate file. In addition, if the appType is JAVA_APP, 128 * this archive name will be added to the front of the classpath so the new 129 * files in the archive will be used first.</LI> 130 * <LI><I><U>remoteAppJvmParameters</U></I> - a string specifying any parameters 131 * that should go directly to the JVM when executing a Java App. For Example: 132 * -Xmx64m -Xms8m</LI> 133 * <LI><I><U>remoteAppJvmClasspath</U></I> - a string specifying any additional 134 * paths to add to the <I>front</I> of the classpath when executing a Java App. 135 * The path entries in this string <B>must</B> be delimited by ";" because a 136 * ":" might have to used in a DOS drive specification.</LI> 137 * </UL><BR> 138 * <LI><B>All extra entries</B> in the properties file will be passed directly 139 * to the application as commandline parameters.</LI> 140 * </UL><HR> 141 * <P>An Example Properties file might look like:<BR> 142 * <PRE> 143 * # NATIVE Remote Application Description property file 144 * appType=0 145 * remoteAppURL=file:/c:/progra~1/tn.bat 146 * #remoteAppURL=c:\\progra~1\\tn.bat 147 * remoteAppDownloadURL= 148 * remoteAppAutoDownload=false 149 * telnetHost=10.0.0.22 2020 150 * </PRE><P> 151 * OR<BR> 152 * <PRE> 153 * # Java Remote Application Description property file 154 * appType=1 155 * remoteAppURL=SimpleExample 156 * remoteAppDownloadURL=http://somesite.com/updates/MySimpleExample.jar 157 * remoteAppAutoDownload=false 158 * remoteAppJvmParameters=-Xmx64m 159 * extraParm=myParm1 160 * anotherExtraParm=myParm2 161 * </PRE> 162 * OR<BR> 163 * <PRE> 164 * # Java Remote Application Description property file 165 * appType=1 166 * remoteAppURL=TelnetApp.jar 167 * remoteAppDownloadURL=http://somesite.com/updates/TelnetApp.jar 168 * remoteAppAutoDownload=true 169 * remoteAppJvmClasspath=/usr/local/extraclasses.jar;/usr/moreextraclasses.jar 170 * telnetHost=10.0.0.22 2020 171 * </PRE> 172 * 173 * <p>Author: <a href="mailto:tgutwin@webarts.bc.ca">Tom Gutwin P.Eng.</a> 174 * <br>Copyright (C) 2002-2003 <a href="http://www.webarts.bc.ca">Web<i>ARTS</i> 175 * Design</a>, North Vancouver Canada. All Rights Reserved.</p> 176 * @author <a href="mailto:tgutwin@webarts.bc.ca">Tom Gutwin P.Eng.</a> 177 **/ 178public class AutoUpdateApp 179{ 180 /** This var should be defined by an extending class (not required)**/ 181 protected static String appName_ = ""; 182 183 /** The default property filename to use. **/ 184 protected static String appPropertyFilename_ = appName_ + ".prop"; 185 186 187 /** this VM classpath **/ 188 static final String CLASSPATH = System.getProperty("java.class.path"); 189 190 /** Class Constant specifying that the app to run is a native application **/ 191 static public final String NATIVE_APP = "native"; 192 193 /** Class Constant specifying that the app to run is a Java application **/ 194 static public final String JAVA_APP = "java"; 195 196 /** Class Constant specifying that the app to run is a Java Applet **/ 197 static public final String APPLET_APP = "applet"; 198 199 /** 200 * Class Constant specifying that the app to run is a URL Locationto view 201 * using the native webbrowser. 202 **/ 203 public static final String HTTPURL_APP = "httpUrl"; 204 205 /** 206 * Remote Launch Property Key specifying the remote lauch app type.<P>This 207 * is a required property in the supplied properties file. 208 **/ 209 public static final String RMT_APP_TYPE = "appType"; 210 211 /** 212 * Remote Launch Property Key specifying the remote lauch 213 * URL for the RemoteLaunchOperation.HTTPURL_APP app type.<P>This 214 * is a required property in the supplied properties file. 215 **/ 216 public static final String RMT_APP_URL = "remoteAppURL"; 217 218 /** 219 * Remote Launch Property Key specifying the URL of the download for the 220 * Remote Launch APP.<P>This is an optional property in the supplied 221 * properties file. 222 **/ 223 public static final String RMT_APP_DOWNLOADURL = "remoteAppDownloadURL"; 224 225 /** 226 * Remote Launch Property Key specifying the flag (boolean string value) that 227 * specifies if the RemoteLaunchOperation Operation should query the 228 * download server for updated app files.<P>This is an optional property in 229 * the supplied properties file. (default=true) 230 **/ 231 public static final String RMT_APP_AUTODOWNLOAD = "remoteAppAutoDownload"; 232 233 /** 234 * Remote Launch Property Key specifying any parameters that should go to the 235 * JVM when executing a Java App.<P>This is an optional property in 236 * the supplied properties file. (default="") 237 **/ 238 public static final String RMT_APP_JVM_PARAMETERS = "remoteAppJvmParameters"; 239 240 /** 241 * Remote Launch Property Key specifying any parameters that should be added 242 * to the <B>FRONT</B> of the classpath when executing a Java App.<P>This is 243 * an optional property in the supplied properties file. (default="")<P>A 244 * StringTokenizer is used to parse this property value and usessemi colons or 245 * colons as delimiters. <B>Note</B> that spaces are NOT used as delimeters so 246 * they can be used in the paths. 247 **/ 248 public static final String RMT_APP_JVM_CLASSPATH = "remoteAppJvmClasspath"; 249 250 /** 251 * A helper Vector that keeps a table of the Defined Properties. 252 **/ 253 private static Vector definedPropertyKeys = new Vector(); 254 255 /** A holder for the NA Clients System File Separator. **/ 256 private static final String SYSTEM_FILE_SEPERATOR = File.separator; 257 258 /** 259 * A holder for the directory location to save downloaded apps.<P> 260 * Default = <code>./RemoteApps/</code> (or the DOS Equiv. 261 * <code>.\RemoteApps\</code>). 262 **/ 263 private static final String DEFAULT_SAVE_LOCATION = "." + 264 SYSTEM_FILE_SEPERATOR + "RemoteApps" + SYSTEM_FILE_SEPERATOR; 265 266 /** 267 * Remote Launch Parm specifying the remote lauch app type (required). 268 **/ 269 private static String appType_ = JAVA_APP; 270 271 /** 272 * Remote Launch Parm specifying the remote lauched application in the form of 273 * a URL.<P>It gets assigned from the required property RMT_APP_URL in the 274 * supplied properties file. 275 **/ 276 private static URL remoteAppURL_ = null; 277 278 /** The system dependant file path to execute. **/ 279 private static String filePath_ = ""; 280 281 /** The system dependant file path for the downloaded archive file.**/ 282 private static String archiveFilePath_ = ""; 283 284 /** 285 * Remote Launch Parm specifying the URL of the download for the Remote Launch 286 * APP. 287 **/ 288 private static URL remoteAppDownloadURL_ = null; 289 290 /** 291 * Remote Launch Parm specifying the flag (boolean string val) that specifies 292 * if the RemoteLaunchOperation Operation should query the 293 * download server for updated app files.<P>(default=true) 294 **/ 295 private static boolean remoteAppAutoDownload_ = true; 296 297 /** 298 * Remote Launch Parm specifying the any extra commandline parms to send 299 * directly to the jvm.<P>(default="") 300 **/ 301 private static String jvmParameters_ = ""; 302 303 /** 304 * Remote Launch Parm specifying the any extra classpath parms to put at the 305 * front of the classpath when the calling the jvm.<P>(default="")<P>A 306 * StringTokenizer is used to parse this property value. So commas or a space 307 * delimited list of entries will work. 308 **/ 309 private static String jvmClasspath_ = ""; 310 311 /** 312 * A class var to track the progress of the various validation checks that 313 * are performed. 314 **/ 315 private static boolean soFarSoGood_ = true; 316 317 /** 318 * A class var to indicate if the download URL is pointing to an archive file 319 * (ie jar file) instead of the actual executable file.<p>This field gets 320 * used by the updateAppFromServer method to determine where to save the file. 321 * </p> 322 * 323 * @see #updateAppFromServer 324 **/ 325 private static boolean archiveDownload_ = false; 326 327 /** 328 * A class var to record and error message to print out if any of the 329 * validation checks on the properties fail. 330 **/ 331 private static String errorMsg_ = ""; 332 333 /** 334 * A table of strings holding any extra parameter properties that were passed 335 * in the properties file. Extra means anything that do not match any of the 336 * Keys specified above. 337 **/ 338 private static Vector cmdLineParms_ = new Vector(); 339 340 341 /** 342 * Basic constructor for the application. It is empty. The entry for this 343 * app is the <A HREF="#main(java.lang.String[])">main( String[] )</A> or 344 * <A HREF="#runApp(java.util.Properties)">runApp(Properties)</A>methods. 345 * 346 * @see #main 347 * @see #runApp 348 **/ 349 protected AutoUpdateApp() 350 { 351 // not implemented 352 } 353 354 355 /** 356 * The entry point for running an app defined by the passed in properties. 357 * <P><b>This method blocks until the Executed app is complete</b></p> 358 * 359 * @param props the Properties defining the app to run as defined in the main 360 * class description. 361 * 362 * @return the return code from the exec'd application, -1 if the app did not 363 * get executed or the app returned a -1. 364 * 365 * @see #main 366 **/ 367 public static int runApp(Properties props) 368 { 369 int retVal = -1; 370 System.out.println("++ Initializing AutoUpdateApp"); 371 // init the class vars from the Properties file 372 soFarSoGood_ = initialize(props); 373 374 // required parameters are all set up?? 375 if (soFarSoGood_) 376 { 377 // required parms are supplied ... carry on the validation 378 System.out.println("++ Ensuring the Remote app Is Available"); 379 380 // validate that the app is available 381 soFarSoGood_ = ensureTheAppIsAvailable(filePath_); 382 } 383 384 // check for updates 385 if (soFarSoGood_ && remoteAppAutoDownload_ && remoteAppDownloadURL_ != null) 386 { 387 // the return from this DOES not affect soFarSoGood_ because we already 388 // confirmed that the app is available. 389 System.out.println("++ Checking for an update."); 390 checkAndUpdateApp(remoteAppDownloadURL_); 391 } 392 393 // execute 394 if (soFarSoGood_) 395 { 396 // This call blocks until the Executed app is complete 397 System.out.println("++ Executing the app"); 398 retVal = execute(); 399 System.out.println("++ Application Completed: Return code = " + retVal); 400 } 401 402 if (!soFarSoGood_) 403 System.out.println(errorMsg_); 404 405 return retVal; 406 } 407 408 409 /** 410 * The main entry for this app. It performs all the calls to validate, 411 * download and then execute the executable requested in the Properties file 412 * that is passed in as this apps single commandline parameter. 413 * 414 * @param args are the commandline parameters.This app expects ONLY 1 415 * parameter... the absolute file path to the properties file 416 * containing all the info for the Remote App to execute. 417 * 418 * @see #runApp 419 **/ 420 public static void main (String [] args) 421 { 422 if (args.length < 1) 423 runApp(loadPropertiesFile(appPropertyFilename_)); 424 else 425 System.out.println("AutoUpdateApp ERROR - incorrect number of" + 426 "commandline args:\nUSAGE: java -jar " + appName_ + 427 ".jar "); 428 429 //System.exit(0); 430 } 431 432 433 /** 434 * Initializes the apps vars (based on the passed in properties file) 435 * and gets ready to start. 436 * 437 * @return true if everything went okay and we can now start 438 **/ 439 private static boolean initialize(Properties props) 440 { 441 boolean retVal = true; 442 // Validate that we got a properties file args.length ==1 443 if (props == null) 444 retVal = false; 445 else 446 { 447 // set up our helper vector to save us time on compares later on 448 definedPropertyKeys.add(RMT_APP_TYPE); 449 definedPropertyKeys.add(RMT_APP_URL); 450 definedPropertyKeys.add(RMT_APP_DOWNLOADURL); 451 definedPropertyKeys.add(RMT_APP_AUTODOWNLOAD); 452 definedPropertyKeys.add(RMT_APP_JVM_PARAMETERS); 453 definedPropertyKeys.add(RMT_APP_JVM_CLASSPATH); 454 // parse out the needed properties into the class variables 455 retVal = parseProperties(props); 456 } 457 return retVal; 458 } 459 460 461 /** 462 * This helper method checks that the specified file exists, if not it 463 * downloads it from the download URL. 464 * 465 * @return true if everything went okay and we have the file in place. 466 **/ 467 private static boolean ensureTheAppIsAvailable(String filePath) 468 { 469 boolean retVal = true; 470 File executableFile = null; 471 472 if (filePath == null) 473 filePath = ""; 474 475 try 476 { 477 System.out.println("We have the Parms: Remote App URL = " 478 + filePath); 479 if (appType_ == JAVA_APP && 480 !(filePath.trim().toLowerCase().endsWith(".jar")) && 481 !(filePath.trim().toLowerCase().endsWith(".class"))) 482 executableFile = new File(filePath + ".class"); 483 else 484 executableFile = new File(filePath); 485 486 // now get the downloadUrl filename (if it exists) 487 String downloadFilename = ""; 488 if (remoteAppDownloadURL_ != null) 489 { 490 downloadFilename = remoteAppDownloadURL_.getFile(); 491 downloadFilename = DEFAULT_SAVE_LOCATION + 492 downloadFilename.substring(downloadFilename.lastIndexOf("/")+1); 493 } 494 495 if (executableFile.exists()) 496 { 497 if (!executableFile.canRead()) 498 { 499 errorMsg_ = "ERROR: Cannot read " + executableFile.getAbsolutePath(); 500 retVal = false; 501 } 502 else 503 System.out.println("Executable Exists"); 504 } 505 else 506 { 507 // do the initial download/install 508 if (!(new File(downloadFilename)).exists()) 509 { 510 System.out.println("Remote Launch Executable Does NOT Exist, " + 511 "attempting retrieval"); 512 retVal = updateAppFromServer(remoteAppDownloadURL_); 513 } 514 } 515 } 516 catch (SecurityException securityEx) 517 { 518 errorMsg_ = "ERROR: A Java Security Manager is in use and is " + 519 "restricting execution of the " + filePath + 520 " application."; 521 retVal = false; 522 } 523 // catch anything else here 524 catch (Exception otherEx) 525 { 526 errorMsg_ = "ERROR: An unforseen " + otherEx.getMessage() + "exception " + 527 "occured while asserting the " + filePath + 528 " application was available.\nIt will NOT execute."; 529 retVal = false; 530 } 531 532 return retVal; 533 } 534 535 536 /** 537 * Searches the classpath for the specified filename and then returns the full 538 * path that is used for it. 539 * 540 * @return the path description of the passed filename as found in the 541 * classpath. 542 **/ 543 private static String getFilePathFromClasspath(String filename) 544 { 545 String retVal = ""; 546 String pathSep = System.getProperty("path.separator"); 547 548 int fileIndex = CLASSPATH.indexOf(filename); 549 //System.out.println("Searching the Classpath for " + filename + " " +fileIndex); 550 if (fileIndex>=0) 551 { 552 int startSpot = 0; 553 int nextSpot = CLASSPATH.indexOf(pathSep); 554 // the fileName is in the classpath 555 // System.out.print("Start Looking at ("+startSpot+","+nextSpot+")"); 556 while ((nextSpot < fileIndex) && nextSpot != -1) 557 { 558 startSpot = nextSpot; 559 nextSpot = CLASSPATH.indexOf(pathSep,startSpot+1); 560 //System.out.print(", ("+startSpot+","+nextSpot+")"); 561 } 562 if (startSpot <= 0) startSpot = -1; 563 if (nextSpot <= 0) nextSpot = CLASSPATH.length() ; 564 retVal = CLASSPATH.substring(startSpot+1, nextSpot); 565 } 566 567 return retVal; 568 } 569 570 571 /** 572 * Converts the path component of a URL to the native relative file path. 573 * 574 * @param url the url to use to convert. 575 * 576 * @return the converted path string. It will return a "" if the URL does not 577 * include a filepath portion. 578 **/ 579 public static String convertSystemDependantPath(URL url) 580 { 581 String retVal = ""; 582 583 // First check if we need to do the '/' conversion 584 if (url != null && SYSTEM_FILE_SEPERATOR.equals("\\")) 585 { 586 // yup... we have to switch 'em 587 // gotta use getFile instead of getPath which is a jdk 1.3 method 588 String tempPath = url.getFile(); 589 for ( int i = 0; i < tempPath.length();i++) 590 { 591 if (tempPath.charAt(i) != '/' ) 592 { 593 retVal += tempPath.substring(i,i+1); 594 } 595 else 596 { 597 if (i != 0) 598 retVal += "\\"; 599 } 600 } 601 } 602 else if (url != null) 603 // It is a Un*x path (no conversion needed) 604 retVal = url.getFile().substring(1); 605 606 return retVal; 607 } 608 609 610 /** 611 * Determines the app type that has been assigned to the class variables and 612 * calls the correct helper method that Executes the class defined remote app. 613 * It Expects that all the class vars that desribe the app are in place and 614 * valid. 615 * 616 **/ 617 private static int execute() 618 { 619 int retVal = -1; 620 621 if(appType_.equals(NATIVE_APP)) 622 { 623 retVal = executeNativeApp(filePath_, 624 cmdLineParms_); 625 } 626 else if(appType_.equals(JAVA_APP)) 627 { 628 // first we have to build the JVM parameters Vector 629 Vector jvmParmVector = null; 630 if (!"".equals(jvmParameters_)) 631 { 632 jvmParmVector = new Vector(); 633 StringTokenizer s = new StringTokenizer(jvmParameters_); 634 while (s.hasMoreTokens()) 635 { 636 jvmParmVector.add(s.nextToken()); 637 } 638 } 639 retVal = executeJavaApp(filePath_, 640 jvmParmVector, 641 cmdLineParms_); 642 } 643 else if(appType_.equals(APPLET_APP)) 644 { 645 // not implemented 646 errorMsg_ = "Applet type remote apps not yet supported"; 647 soFarSoGood_ = false; 648 } 649 else if(appType_.equals(HTTPURL_APP)) 650 { 651 // not implemented 652 errorMsg_ = "HTTP URL type remote apps not yet supported"; 653 soFarSoGood_ = false; 654 } 655 656 return retVal; 657 } 658 659 660 /** 661 * Parses a String representation of a URL or absolute file path and converts 662 * it into a URL.<P>This method is a bit forgiving... if the string is not 663 * a correctlty formatted http, ftp, or file URL it will assume it is a file 664 * URL and create the returned URL as such. 665 * 666 * @param value is the String to convert into a URL. 667 * 668 * @return the Valid URL for the Executable or null if this method failed to 669 * convert the passed in string. 670 * 671 * @throws MalformedURLException if the passed in String is not a URL 672 **/ 673 private static URL parseAppExecutableUrl(String value) 674 throws MalformedURLException 675 { 676 URL retVal = null; 677 if (value.toLowerCase().startsWith("http:/") || 678 value.toLowerCase().startsWith("ftp:/") || 679 value.toLowerCase().startsWith("file:/")) 680 { 681 // the following throws a MalformedURLException if value is bad 682 retVal = new URL(value); 683 } 684 else // assume it is a file path 685 { 686 try 687 { 688 String tempPath = value; // Assume Un*x ... no replacement needed 689 if (SYSTEM_FILE_SEPERATOR.equals("\\")) 690 { 691 /* Replace the file separators with the forward slash */ 692 tempPath = ""; // start from scratch 693 for ( int i = 0; i < value.length(); i++) 694 { 695 if (value.charAt(i) != SYSTEM_FILE_SEPERATOR.charAt(0) ) 696 { 697 tempPath += value.substring(i,i+1); 698 } 699 else 700 { 701 tempPath += "/"; 702 } 703 } 704 } 705 retVal = new URL("file:/" + tempPath); 706 } 707 catch (NullPointerException badUrl) 708 { 709 throw new MalformedURLException( 710 "Can't parse the location URL from the file path provided."); 711 } 712 } 713 return retVal; 714 } 715 716 717 /** 718 * Checks the specified remoteAppDownloadURL_ to see if there is a newer 719 * version of the remoteAppURL_ <B>AND </B>then goes out and updates the app 720 * if a newer one is available. 721 * 722 * @param urlToGet is the place to go to get the updated app. 723 * 724 * @return true if there is a newer version available and it was download 725 * successfully. 726 * 727 * @see #remoteAppDownloadURL_ 728 * @see #remoteAppURL_ 729 **/ 730 private static boolean checkAndUpdateApp(URL urlToGet) 731 { 732 boolean retVal = false; 733 if (checkForUpdatedApp()) 734 retVal = updateAppFromServer(urlToGet); 735 736 return retVal; 737 } 738 739 740 /** 741 * Checks the specified remoteAppDownloadURL_ to see if there is a newer 742 * version of the remoteAppURL_. 743 * 744 * @return true if there is a newer version available 745 * 746 * @see #checkAndUpdateApp 747 * @see #remoteAppDownloadURL_ 748 * @see #remoteAppURL_ 749 **/ 750 private static boolean checkForUpdatedApp() 751 { 752 boolean retVal = false; 753 if (filePath_ == null) 754 filePath_ = ""; 755 756 try 757 { 758 File executableFile = null; 759 760 if (appType_ == JAVA_APP && 761 !(filePath_.trim().toLowerCase().endsWith(".jar")) && 762 !(filePath_.trim().toLowerCase().endsWith(".class"))) 763 executableFile = new File(filePath_ + ".class"); 764 else 765 executableFile = new File(filePath_); 766 767 if (executableFile.exists()) 768 { 769 if (executableFile.canRead()) 770 { 771 long localModTime = executableFile.lastModified(); 772 URLConnection remoteConn = 773 (URLConnection) remoteAppDownloadURL_.openConnection(); 774 if (remoteConn.getLastModified() > localModTime) 775 retVal = true; 776 } 777 } 778 else 779 // check the download file 780 { 781 if (remoteAppDownloadURL_ != null) 782 { 783 // Parse out the filename portion of the download url 784 String downloadFilename = remoteAppDownloadURL_.getFile(); 785 downloadFilename = DEFAULT_SAVE_LOCATION + 786 downloadFilename.substring(downloadFilename.lastIndexOf("/")+1); 787 788 // now create a file Object based on the above info so we can check 789 // dates 790 File localDownloadFile = new File(downloadFilename); 791 if (localDownloadFile.exists()) 792 { 793 if (localDownloadFile.canRead()) 794 { 795 long localModTime = localDownloadFile.lastModified(); 796 URLConnection remoteConn = 797 (URLConnection) remoteAppDownloadURL_.openConnection(); 798 if (remoteConn.getLastModified() > localModTime) 799 { 800 retVal = true; 801 } 802 } 803 } 804 } 805 } 806 } 807 catch (IOException ioEx) 808 { 809 System.out.println("Cannot check for updates at this time: " + 810 "The remote download URL specified " + remoteAppDownloadURL_ + 811 "is not permitting a connection.\nUsing current local file."); 812 } 813 return retVal; 814 } 815 816 817 /** 818 * Downloads the requested URL and replaces any existing version.<P>The place 819 * for saving this downloaded file is determined based on the archiveDownload_ 820 * flag. If archiveDownload_is true then dowloaded file is saved as a new 821 * /updated file with its own filename. This is done when an archive file is 822 * used as the download that is not the same as the executable name found in 823 * the remoteAppURL_ field. For example: if remoteAppURL_ points to 824 * ca.bc.webarts.SomeClass and the remoteAppDownloadURL_ points to 825 * SomeClass.jar we need to save the downloaded file to SomeClass.jar and then 826 * assume the commandline parameters will take care of the running/classpath 827 * issues. 828 * 829 * @param urlToGet is the place to go to get the updated app. 830 * 831 * @return true if successfully updated 832 * 833 * @see #archiveDownload_ 834 **/ 835 private static boolean updateAppFromServer(URL urlToGet) 836 { 837 boolean retVal = false; 838 839 if (urlToGet != null) 840 { 841 String filename = urlToGet.getFile(); 842 843 // get the filename of the download 844 String remoteAppName = filename.substring(filename.lastIndexOf("/")+1); 845 846 // check if the remote download filename is the same as our Executable 847 // file name (we need this if the exe/class file is in an Jar archive etc 848 if (archiveDownload_) 849 { 850 // write to a new file 851 filename = DEFAULT_SAVE_LOCATION + remoteAppName; 852 archiveFilePath_ = filename; 853 } 854 else 855 // if so just overwrite the exe/class file 856 filename = filePath_; 857 858 //go get it 859 try 860 { 861 System.out.print("Downloading an update for: " + 862 filename + " <"); 863 URLConnection connection = 864 (URLConnection) urlToGet.openConnection(); 865 System.out.println(connection.getContentType() + "> ("+ 866 connection.getContentLength() + ")"); 867 System.out.println(" FROM: " + urlToGet); 868 869 // Store the file locally 870 InputStream inUrl = null; 871 if (urlToGet.getProtocol().equals("http")) 872 inUrl = ((HttpURLConnection) connection).getInputStream(); 873 else 874 inUrl = connection.getInputStream(); 875 new File(DEFAULT_SAVE_LOCATION).mkdir(); // ensures the dir exests 876 FileOutputStream ostream = new FileOutputStream(filename); 877 878 // start transfering 879 byte [] bytesRead= new byte[1024]; 880 int numBytes = inUrl.read(bytesRead); 881 int status = 0; 882 System.out.print(".."); 883 while (numBytes != -1) 884 { 885 // write what we read 886 ostream.write(bytesRead, 0, numBytes); 887 888 // update our status indicator 889 status += numBytes; 890 if (status % 1024 == 0) 891 System.out.print("."); 892 893 // go back for more 894 numBytes = inUrl.read(bytesRead); 895 } 896 System.out.println("."); 897 ostream.close(); 898 retVal = true; 899 } 900 catch (NullPointerException nullEx) 901 { 902 System.out.println("Cannot update" + filename + " at this time: "); 903 System.out.println("Reason: Cannot get the content from " + 904 urlToGet.toString()); 905 System.out.println("Using current local file."); 906 } 907 catch (MalformedURLException badUrlEx) 908 { 909 System.out.println("Cannot update" + filename + " at this time: "); 910 System.out.println("Reason: Cannot get the URL for " + 911 filename); 912 System.out.println("Using current local file."); 913 } 914 catch (SecurityException secEx) 915 { 916 System.out.println("Cannot update" + filename + " at this time: "); 917 System.out.println("Reason: Cannot create the file due to security " + 918 "reasons."); 919 System.out.println("Using current local file."); 920 } 921 catch (FileNotFoundException fnfEx) 922 { 923 System.out.println("Cannot update" + filename + " at this time: "); 924 System.out.println("Reason: Cannot write the File."); 925 System.out.println("Using current local file."); 926 } 927 catch (IOException ioEx) 928 { 929 System.out.println("Cannot update" + filename + " at this time: "); 930 System.out.println("Reason: The remote download URL specified " + 931 urlToGet + "is not permitting a connection."); 932 System.out.println("Using current local file."); 933 } 934 } 935 936 return retVal; 937 } 938 939 940 /** 941 * Executes the Specified Native OS application with the provided commandline 942 * parameters. This method blocks until the Executed app is complete. It also 943 * cleans up its sub-process and garbage collects. 944 * <br><b><u> 945 * NOTE:</b></u> This method uses a vector for the appParams and DOES NOT guaranty 946 * parameter order. Please use the 947 * <a href="#executeNativeApp(java.lang.String, java.lang.String[])"> 948 * executeNativeApp(String executableLocation, String [] cmdParms)</a> method\ 949 * which uses an array for storage/retreival of the app parms. 950 * 951 * @param executableLocation is the path to the executable to run 952 * 953 * @param appParms and extra commandline parameters to tag onto the end of the 954 * commandline that gets executed. 955 * 956 * @return returns the return code from the executed app/process 957 * 958 * @see #executeNativeApp(java.lang.String, java.lang.String[]) 959 * @see StreamGobbler 960 * @see java.lang.Runtime#getRuntime 961 **/ 962 protected static int executeNativeApp(String executableLocation, 963 Vector appParms) 964 { 965 int cmdParms = 0; 966 if (appParms != null) 967 cmdParms = appParms.size(); 968 String [] cmds = new String [cmdParms+1]; 969 970 for (int i=1; i <= cmdParms; i++) 971 { 972 cmds[i] = (String) appParms.elementAt(i-1); 973 } 974 return executeNativeApp(executableLocation, cmds); 975 } 976 977 978 /** 979 * Executes the Specified Native OS application with the provided commandline 980 * parameters. This method blocks until the Executed app is complete. It also 981 * cleans up its sub-process and garbage collects. This method sends app 982 * output to std out. 983 * 984 * @param executableLocation is the path to the executable to run 985 * 986 * @param cmdParms and extra commandline parameters to tag onto the end of the 987 * commandline that gets executed. 988 * 989 * @return returns the return code from the executed app/process 990 * 991 * @see StreamGobbler 992 * @see java.lang.Runtime#getRuntime 993 **/ 994 public static int executeNativeApp(String executableLocation, 995 String [] cmdParms) 996 { 997 return executeNativeApp(executableLocation, cmdParms, null); 998 } 999 1000 1001 /** 1002 * Executes the Specified Native OS application with the provided commandline 1003 * parameters. This method blocks until the Executed app is complete. It also 1004 * cleans up its sub-process and garbage collects. 1005 * 1006 * @param executableLocation is the path to the executable to run 1007 * 1008 * @param cmdParms and extra commandline parameters to tag onto the end of the 1009 * commandline that gets executed. 1010 * 1011 * @param outputFilename a filename to send the output to. 1012 * 1013 * @return returns the return code from the executed app/process 1014 * 1015 * @see StreamGobbler 1016 * @see java.lang.Runtime#getRuntime 1017 **/ 1018 public static int executeNativeApp(String executableLocation, 1019 String [] cmdParms, 1020 String outputFilename) 1021 { 1022 int retVal = -1; 1023 //int cmdParms = 0; 1024 //if (appParms != null) 1025 // cmdParms = appParms.size(); 1026 String [] cmds = new String [cmdParms.length+1]; 1027 cmds[0] = executableLocation; 1028 1029 System.out.print("\nParms: "); 1030 for (int i=1; i <= cmdParms.length; i++) 1031 { 1032 cmds[i] = (String) cmdParms[i-1]; 1033 System.out.print(" " + cmds[i]); 1034 } 1035 System.out.println(""); 1036 1037 // Start the app... This starts a new process 1038 try 1039 { 1040 File appDirfile = Util.getFileDir(executableLocation); 1041 System.out.println("Executable Dir : "+ appDirfile.getAbsolutePath()); 1042 Runtime runtime = Runtime.getRuntime(); 1043 System.out.println("Executing: "+ cmds[0]); 1044 Process p = runtime.exec(cmds, null, appDirfile); 1045 1046 // capture any output we get 1047 // any error message? 1048 StreamGobbler errorGobbler = new StreamGobbler(p.getErrorStream(), "APP ERR:"); 1049 1050 // redirect any output? 1051 FileOutputStream pumpedOutputFile = null; 1052 PrintStream printStream = null; 1053 if (outputFilename != null && !outputFilename.equals("")) 1054 { 1055 pumpedOutputFile = new FileOutputStream(outputFilename); 1056 printStream =new PrintStream(pumpedOutputFile); 1057 System.out.println("Output Redirected to file: "+ outputFilename); 1058 } 1059 StreamGobbler outputGobbler = new 1060 StreamGobbler(p.getInputStream(), "", printStream); 1061 outputGobbler.setCapture(true); 1062 1063 // kick them off 1064 errorGobbler.start(); 1065 outputGobbler.start(); 1066 //Util.sleep(1000); // give the gobbler time to get all the output 1067 1068 // now wait for the process to end 1069 try 1070 { 1071 p.waitFor(); 1072 } 1073 catch (InterruptedException intEx) 1074 { 1075 // no biggie 1076 System.out.print("Process "+ cmds[0] +" Interupted?"); 1077 } 1078 retVal = p.exitValue(); 1079 Util.sleep(1000); // give the gobbler time to get all the output 1080 errorGobbler.finishedGobbling_ = true; 1081 outputGobbler.finishedGobbling_ = true; 1082 p.destroy(); 1083 p = null; 1084 runtime.gc(); 1085 } 1086 catch (IOException ioEx) 1087 { 1088 errorMsg_ = "ERROR: An IO exception occured while attempting " + 1089 "execution of the " + executableLocation + " application."; 1090 soFarSoGood_ = false; 1091 } 1092 catch (SecurityException securityEx) 1093 { 1094 errorMsg_ = "ERROR: A Java Security Manager is in use and is " + 1095 "restricting execution of the " + executableLocation + " application."; 1096 soFarSoGood_ = false; 1097 } 1098 catch (Exception ex) 1099 { 1100 errorMsg_ = "ERROR: A Java Exception Occured" + 1101 "restricting execution of the " + executableLocation + " application."; 1102 soFarSoGood_ = false; 1103 } 1104 1105 return retVal; 1106 } 1107 1108 1109 /** 1110 * Executes the Specified Java appilcation with the provided commandline 1111 * parameters. 1112 * 1113 * @param classLocation is the path to the executable to run 1114 * 1115 * @param appParms and extra commandline parameters to tag onto the end of the 1116 * commandline that gets executed. 1117 * @return returns the return code from the executed app/process 1118 **/ 1119 protected static int executeJavaApp(String classLocation, Vector appParms) 1120 { 1121 return executeJavaApp(classLocation, null, appParms); 1122 } 1123 1124 1125 /** 1126 * Executes the Specified Java appilcation with the provided JVM parameters 1127 * and executableApp commandline parameters. 1128 * 1129 * @param classLocation is the path to the executable to run 1130 * 1131 * @param jvmParms holds any cmdline parms to send directly to the jvm 1132 * 1133 * @param appParms and extra commandline parameters to tag onto the end of the 1134 * commandline that gets executed. 1135 * @return returns the return code from the executed app/process 1136 **/ 1137 protected static int executeJavaApp(String classLocation, 1138 Vector jvmParms, 1139 Vector appParms) 1140 { 1141 int retVal = -1; 1142 int cmdParms = 0; 1143 if (appParms != null) 1144 cmdParms = appParms.size(); 1145 Vector v = new Vector(); 1146 int vCounter = 0; 1147 1148 // add the JVM parms first 1149 if (jvmParms != null) 1150 { 1151 int jvmParmSize = jvmParms.size(); 1152 // add all the JVM parameters 1153 for (int i=0; i< jvmParmSize; i++) 1154 { 1155 v.add(vCounter++,(String)jvmParms.elementAt(i)); 1156 } 1157 } 1158 1159 // Add the classpath parm (if it is not empty) 1160 if (archiveDownload_) 1161 jvmClasspath_ = archiveFilePath_+ File.pathSeparator + jvmClasspath_; 1162 1163 if (!"".equals(jvmClasspath_)) 1164 { 1165 v.add(vCounter++,"-cp"); 1166 v.add(vCounter++,jvmClasspath_); 1167 } 1168 1169 // verify if the java app is a class or jar file 1170 // if it is a jar we have to provide the extra -jar item on the cmdline 1171 // this assumes the jar is set up to be autoexecuting jar 1172 if (classLocation.trim().toLowerCase().endsWith("jar")) 1173 v.add(vCounter++,"-jar"); 1174 v.add(vCounter++,classLocation); 1175 1176 // add all the extra parameters following the class/jar file 1177 for (int i=0; i < cmdParms; i++) 1178 { 1179 v.add(vCounter++,(String)appParms.elementAt(i)); 1180 } 1181 1182 /* 1183 cmdParms = v.size(); 1184 System.out.print("Parms: "); 1185 for (int i=1; i <= cmdParms; i++) 1186 { 1187 System.out.print(" " + (String) v.elementAt(i-1)); 1188 } 1189 System.out.println(""); 1190 */ 1191 1192 String javaHome = System.getProperty("java.home"); 1193 appParms.add(classLocation); 1194 retVal = executeNativeApp(javaHome + SYSTEM_FILE_SEPERATOR +"bin" + 1195 SYSTEM_FILE_SEPERATOR + "java", v); 1196 return retVal; 1197 } 1198 1199 1200 /** 1201 * Parses the passed in Properties and pulls out all the name/value pairs 1202 * and assigns them to the class vars as needed. 1203 * 1204 * @param props the Properties to parse 1205 * 1206 * @return true if the method was able to successfully assign all class vars 1207 * 1208 **/ 1209 private static boolean parseProperties(Properties props) 1210 { 1211 boolean retVal = true; 1212 1213 // grab out the name/value pairs 1214 // app type 1215 if (props.containsKey(RMT_APP_TYPE)) 1216 { 1217 appType_ = props.getProperty(RMT_APP_TYPE); 1218 } 1219 else 1220 { 1221 errorMsg_ = "Can't parse the required parameter: application type."; 1222 retVal = false; 1223 } 1224 1225 // app locator 1226 if (retVal && props.containsKey(RMT_APP_URL)) 1227 { 1228 try 1229 { 1230 remoteAppURL_ = parseAppExecutableUrl(props.getProperty(RMT_APP_URL)); 1231 filePath_ = convertSystemDependantPath(remoteAppURL_); 1232 } 1233 catch (MalformedURLException badUrl) 1234 { 1235 errorMsg_ = "Can't parse the location URL for the application " + 1236 "to execute"; 1237 retVal = false; 1238 } 1239 } 1240 else 1241 { 1242 errorMsg_ = "Can't parse the required parameter: application location."; 1243 retVal = false; 1244 } 1245 1246 String tempVal = null; 1247 // optional autodownload flag 1248 if (retVal && props.containsKey(RMT_APP_AUTODOWNLOAD)) 1249 { 1250 tempVal = (String) props.get(RMT_APP_AUTODOWNLOAD); 1251 if (tempVal != null) 1252 remoteAppAutoDownload_ = ( 1253 "false".equals(tempVal.trim().toLowerCase())? 1254 false: 1255 true); 1256 } 1257 1258 // optional download url 1259 if (retVal && 1260 props.containsKey(RMT_APP_DOWNLOADURL)) 1261 { 1262 try 1263 { 1264 remoteAppDownloadURL_ = 1265 new URL((String) props.get(RMT_APP_DOWNLOADURL)); 1266 1267 // check and set the archiveDownload_ indicator 1268 String remoteFilename = remoteAppDownloadURL_.getFile(); 1269 1270 // get our path for saving set up 1271 String remoteAppName = 1272 remoteFilename.substring(remoteFilename.lastIndexOf("/")+1); 1273 String localAppName = 1274 filePath_.substring(filePath_.lastIndexOf(SYSTEM_FILE_SEPERATOR)+1); 1275 1276 // check if the remote download filename is the same as our Executable 1277 // file name. Set archiveDownload_if the exe/class file is in 1278 // an archive (ie Jar or maybe a zip) 1279 // this gets used be the Auto Download feature (updateAppFromServer) 1280 if (remoteAppName != null && !remoteAppName.equals(localAppName)) 1281 { 1282 // if so just overwrite the exe/class file 1283 archiveDownload_ = true; 1284 archiveFilePath_ = DEFAULT_SAVE_LOCATION + remoteAppName; 1285 } 1286 else 1287 filePath_ = DEFAULT_SAVE_LOCATION + remoteAppName; 1288 } 1289 catch (MalformedURLException badUrl) 1290 { 1291 // This is Okay because this Property is an optional one. 1292 // so just inform the user 1293 System.out.println("WARNING: Can't parse the supplied location URL " + 1294 "to download the application to execute."); 1295 System.out.println("Using current local file."); 1296 } 1297 } 1298 1299 // optional jvm parms string 1300 if (retVal && props.containsKey(RMT_APP_JVM_PARAMETERS)) 1301 { 1302 jvmParameters_ = props.getProperty(RMT_APP_JVM_PARAMETERS); 1303 } 1304 1305 // optional jvm classpath string 1306 if (retVal && props.containsKey(RMT_APP_JVM_CLASSPATH)) 1307 { 1308 StringTokenizer st = new StringTokenizer( 1309 props.getProperty(RMT_APP_JVM_CLASSPATH), ";"); 1310 while (st.hasMoreTokens()) 1311 { 1312 // add them to the FRONT of any existing jvmClasspath_ 1313 jvmClasspath_ = st.nextToken() + 1314 (jvmClasspath_==""?"":File.pathSeparator + jvmClasspath_); 1315 } 1316 } 1317 1318 // grab out all the rest 1319 for (Enumeration myEnum = props.keys(); myEnum.hasMoreElements();) 1320 { 1321 String currentPropKey = (String) myEnum.nextElement(); 1322 if (currentPropKey != null && 1323 !definedPropertyKeys.contains(currentPropKey)) 1324 { 1325 // tokenize any extra parms if it can 1326 tempVal = props.getProperty(currentPropKey); 1327 StringTokenizer st = new StringTokenizer(tempVal); 1328 while (st.hasMoreTokens()) 1329 { 1330 cmdLineParms_.add(st.nextToken()); 1331 } 1332 } 1333 } 1334 1335 return retVal; 1336 } 1337 1338 1339 /** 1340 * Loads the AutoDownload app information from the properties file so this 1341 * wrapped app can execute. The properties file is encased in the root dir of 1342 * this apps jar file. 1343 * 1344 * @return the parsed Properties contained in the file specified by the passed 1345 * in appPropertyFilename_, null if unable to get the contained 1346 * Properties 1347 **/ 1348 protected static Properties loadAutoAppPropertiesFile() 1349 { 1350 Properties props = null; 1351 boolean errorOccured = true; 1352 InputStream in = null; 1353 JarEntry autoAppPropsJarEntry = null; 1354 String currDir = System.getProperty("user.dir"); 1355 String thisJarFile = currDir + SYSTEM_FILE_SEPERATOR + appName_+".jar"; 1356 String jarInClasspath = getFilePathFromClasspath(appName_+".jar"); 1357 String fileInCurrDir = currDir + SYSTEM_FILE_SEPERATOR + 1358 appPropertyFilename_; 1359 1360 try 1361 { 1362 // first check the current directory for a jar file with this appsname.jar 1363 File tempFile = new File(thisJarFile); 1364 if (tempFile == null || !tempFile.exists() || !tempFile.canRead()) 1365 { 1366 // if no jar in the current dir then going looking in the classpath 1367 tempFile = new File(jarInClasspath); 1368 if (tempFile == null || !tempFile.exists() || !tempFile.canRead()) 1369 { 1370 // Last resort look for an unzipped set of files 1371 tempFile = new File(fileInCurrDir); 1372 if (tempFile == null || !tempFile.exists() || !tempFile.canRead()) 1373 { 1374 // Not Found Anywhere 1375 thisJarFile = null; 1376 } 1377 else 1378 { 1379 // Its an Unzipped Archive 1380 // So load the props right here (leave errorOccured = true 1381 try 1382 { 1383 in = new FileInputStream(tempFile); 1384 props = new Properties(); 1385 props.load(in); 1386 errorOccured = false; 1387 } 1388 catch (FileNotFoundException fEx) 1389 { 1390 System.out.println("No Application Properties File " + 1391 "FileNotFoundException " + appPropertyFilename_); 1392 } 1393 catch (IOException ioEx) 1394 { 1395 System.out.println("IO Error Reading Properties File " + 1396 "FileNotFoundException " + appPropertyFilename_); 1397 } 1398 } 1399 } 1400 else 1401 { 1402 // Its in The Classpath 1403 thisJarFile = jarInClasspath; 1404 errorOccured = false; 1405 } 1406 } 1407 else 1408 // Its in the Jar 1409 errorOccured = false; 1410 } 1411 catch (NullPointerException fEx) 1412 { 1413 thisJarFile = null; 1414 } 1415 1416 try 1417 { 1418 if (!errorOccured) // if in jar or jar in classpath 1419 { 1420 System.out.println(" +++ Looking for Jar File \n" + thisJarFile); 1421 JarFile jar = new JarFile(thisJarFile, false); 1422 autoAppPropsJarEntry = jar.getJarEntry(appPropertyFilename_); 1423 System.out.println("appPropertyFilename_="+appPropertyFilename_); 1424 System.out.println("autoAppPropsJarEntry="+ 1425 (autoAppPropsJarEntry==null?"null":"valid")); 1426 in = jar.getInputStream(autoAppPropsJarEntry); 1427 props = new Properties(); 1428 props.load(in); 1429 errorOccured = false; 1430 } 1431 } 1432 catch (NullPointerException fEx) 1433 { 1434 System.out.println("No Application Properties JarEntry " + 1435 "NullPointerException " + appPropertyFilename_); 1436 } 1437 catch (FileNotFoundException fEx) 1438 { 1439 System.out.println("No Application Properties JarEntry " + 1440 "FileNotFoundException " + appPropertyFilename_); 1441 } 1442 catch (IOException ioEx) 1443 { 1444 System.out.println("IO Error Reading Properties JarEntry " + 1445 "FileNotFoundException " + appPropertyFilename_); 1446 } 1447 catch (SecurityException secEx) 1448 { 1449 System.out.println("Jar SecurityException " + thisJarFile); 1450 } 1451 1452 return props; 1453 } 1454 1455 1456 /** 1457 * Loads the passed Properties file and returns a Properties object. 1458 * 1459 * @param propFilename the filename for the Properties file to parse 1460 * 1461 * @return the parsed Properties contained in the file specified by the passed 1462 * in propFilename, null if unable to get the contained Properties 1463 * 1464 **/ 1465 protected static Properties loadPropertiesFile(String propFilename) 1466 { 1467 Properties props = new Properties(); 1468 try 1469 { 1470 // validate that the properties file exists 1471 FileInputStream propFileIn = new FileInputStream(propFilename); 1472 1473 // Load the Properties File 1474 props.load(propFileIn); 1475 1476 } 1477 catch (FileNotFoundException fnfEx) 1478 { 1479 // the path is null 1480 props = null; 1481 errorMsg_ = "Cannot obtain the application path (File Not Found)."; 1482 } 1483 catch (IOException ioEx) 1484 { 1485 // the path is null 1486 props = null; 1487 errorMsg_ = "Cannot obtain the application path (I/O Error)."; 1488 } 1489 return props; 1490 } 1491}