001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.tools; 028 import org.opends.messages.Message; 029 030 031 032 import java.io.File; 033 import java.io.RandomAccessFile; 034 035 import org.opends.server.util.args.ArgumentException; 036 import org.opends.server.util.args.ArgumentParser; 037 import org.opends.server.util.args.BooleanArgument; 038 import org.opends.server.util.args.IntegerArgument; 039 import org.opends.server.util.args.StringArgument; 040 041 import static org.opends.messages.ToolMessages.*; 042 import static org.opends.server.util.ServerConstants.*; 043 import static org.opends.server.util.StaticUtils.*; 044 045 046 047 /** 048 * This program provides a simple tool that will wait for a specified file to be 049 * deleted before exiting. It can be used in the process of confirming that the 050 * server has completed its startup or shutdown process. 051 */ 052 public class WaitForFileDelete 053 { 054 /** 055 * The fully-qualified name of this class. 056 */ 057 private static final String CLASS_NAME = 058 "org.opends.server.tools.WaitForFileDelete"; 059 060 061 062 /** 063 * The exit code value that will be used if the target file is deleted 064 * successfully. 065 */ 066 public static final int EXIT_CODE_SUCCESS = 0; 067 068 069 070 /** 071 * The exit code value that will be used if an internal error occurs within 072 * this program. 073 */ 074 public static final int EXIT_CODE_INTERNAL_ERROR = 1; 075 076 077 078 /** 079 * The exit code value that will be used if a timeout occurs while waiting for 080 * the file to be removed. 081 */ 082 public static final int EXIT_CODE_TIMEOUT = 2; 083 084 085 086 /** 087 * Processes the command-line arguments and initiates the process of waiting 088 * for the file to be removed. 089 * 090 * @param args The command-line arguments provided to this program. 091 */ 092 public static void main(String[] args) 093 { 094 try 095 { 096 int exitCode = mainWait(args); 097 if (exitCode != EXIT_CODE_SUCCESS) 098 { 099 System.exit(filterExitCode(exitCode)); 100 } 101 } 102 catch (Exception e) 103 { 104 e.printStackTrace(); 105 System.exit(EXIT_CODE_INTERNAL_ERROR); 106 } 107 } 108 109 110 111 /** 112 * Processes the command-line arguments and then waits for the specified file 113 * to be removed. 114 * 115 * @param args The command-line arguments provided to this program. 116 * 117 * @return An integer value of zero if the file was deleted successfully, or 118 * some other value if a problem occurred. 119 */ 120 public static int mainWait(String[] args) 121 { 122 // Create all of the command-line arguments for this program. 123 BooleanArgument showUsage = null; 124 IntegerArgument timeout = null; 125 StringArgument logFilePath = null; 126 StringArgument targetFilePath = null; 127 StringArgument outputFilePath = null; 128 129 Message toolDescription = INFO_WAIT4DEL_TOOL_DESCRIPTION.get(); 130 ArgumentParser argParser = new ArgumentParser(CLASS_NAME, toolDescription, 131 false); 132 133 try 134 { 135 targetFilePath = 136 new StringArgument("targetfile", 'f', "targetFile", true, false, 137 true, INFO_PATH_PLACEHOLDER.get(), null, null, 138 INFO_WAIT4DEL_DESCRIPTION_TARGET_FILE.get()); 139 argParser.addArgument(targetFilePath); 140 141 142 logFilePath = new StringArgument( 143 "logfile", 'l', "logFile", false, false, 144 true, INFO_PATH_PLACEHOLDER.get(), null, null, 145 INFO_WAIT4DEL_DESCRIPTION_LOG_FILE.get()); 146 argParser.addArgument(logFilePath); 147 148 149 outputFilePath = new StringArgument( 150 "outputfile", 'o', "outputFile", 151 false, false, 152 true, INFO_PATH_PLACEHOLDER.get(), null, null, 153 INFO_WAIT4DEL_DESCRIPTION_OUTPUT_FILE.get()); 154 argParser.addArgument(outputFilePath); 155 156 157 timeout = new IntegerArgument("timeout", 't', "timeout", true, false, 158 true, INFO_SECONDS_PLACEHOLDER.get(), 60, 159 null, true, 0, false, 160 0, INFO_WAIT4DEL_DESCRIPTION_TIMEOUT.get()); 161 argParser.addArgument(timeout); 162 163 164 showUsage = new BooleanArgument("help", 'H', "help", 165 INFO_WAIT4DEL_DESCRIPTION_HELP.get()); 166 argParser.addArgument(showUsage); 167 argParser.setUsageArgument(showUsage); 168 } 169 catch (ArgumentException ae) 170 { 171 Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage()); 172 System.err.println(wrapText(message, MAX_LINE_WIDTH)); 173 return EXIT_CODE_INTERNAL_ERROR; 174 } 175 176 177 // Parse the command-line arguments provided to the program. 178 try 179 { 180 argParser.parseArguments(args); 181 } 182 catch (ArgumentException ae) 183 { 184 Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage()); 185 186 System.err.println(wrapText(message, MAX_LINE_WIDTH)); 187 System.err.println(argParser.getUsage()); 188 return EXIT_CODE_INTERNAL_ERROR; 189 } 190 191 192 // If we should just display usage or version information, 193 // then print it and exit. 194 if (argParser.usageOrVersionDisplayed()) 195 { 196 return EXIT_CODE_SUCCESS; 197 } 198 199 200 // Get the file to watch. If it doesn't exist now, then exit immediately. 201 File targetFile = new File(targetFilePath.getValue()); 202 if (! targetFile.exists()) 203 { 204 return EXIT_CODE_SUCCESS; 205 } 206 207 208 // If a log file was specified, then open it. 209 long logFileOffset = 0L; 210 RandomAccessFile logFile = null; 211 if (logFilePath.isPresent()) 212 { 213 try 214 { 215 File f = new File(logFilePath.getValue()); 216 if (f.exists()) 217 { 218 logFile = new RandomAccessFile(f, "r"); 219 logFileOffset = logFile.length(); 220 logFile.seek(logFileOffset); 221 } 222 } 223 catch (Exception e) 224 { 225 Message message = WARN_WAIT4DEL_CANNOT_OPEN_LOG_FILE.get( 226 logFilePath.getValue(), String.valueOf(e)); 227 System.err.println(wrapText(message, MAX_LINE_WIDTH)); 228 229 logFile = null; 230 } 231 } 232 233 234 // If an output file was specified and we could open the log file, open it 235 // and append data to it. 236 RandomAccessFile outputFile = null; 237 long outputFileOffset = 0L; 238 if (logFile != null) 239 { 240 if (outputFilePath.isPresent()) 241 { 242 try 243 { 244 File f = new File(outputFilePath.getValue()); 245 if (f.exists()) 246 { 247 outputFile = new RandomAccessFile(f, "rw"); 248 outputFileOffset = outputFile.length(); 249 outputFile.seek(outputFileOffset); 250 } 251 } 252 catch (Exception e) 253 { 254 Message message = WARN_WAIT4DEL_CANNOT_OPEN_OUTPUT_FILE.get( 255 outputFilePath.getValue(), String.valueOf(e)); 256 System.err.println(wrapText(message, MAX_LINE_WIDTH)); 257 258 outputFile = null; 259 } 260 } 261 } 262 // Figure out when to stop waiting. 263 long stopWaitingTime; 264 try 265 { 266 long timeoutMillis = 1000L * Integer.parseInt(timeout.getValue()); 267 if (timeoutMillis > 0) 268 { 269 stopWaitingTime = System.currentTimeMillis() + timeoutMillis; 270 } 271 else 272 { 273 stopWaitingTime = Long.MAX_VALUE; 274 } 275 } 276 catch (Exception e) 277 { 278 // This shouldn't happen, but if it does then ignore it. 279 stopWaitingTime = System.currentTimeMillis() + 60000; 280 } 281 282 283 // Operate in a loop, printing out any applicable log messages and waiting 284 // for the target file to be removed. 285 byte[] logBuffer = new byte[8192]; 286 while (System.currentTimeMillis() < stopWaitingTime) 287 { 288 if (logFile != null) 289 { 290 try 291 { 292 while (logFile.length() > logFileOffset) 293 { 294 int bytesRead = logFile.read(logBuffer); 295 if (bytesRead > 0) 296 { 297 if (outputFile == null) 298 { 299 System.out.write(logBuffer, 0, bytesRead); 300 System.out.flush(); 301 } 302 else 303 { 304 // Write on the file. 305 // TODO 306 outputFile.write(logBuffer, 0, bytesRead); 307 308 } 309 logFileOffset += bytesRead; 310 } 311 } 312 } 313 catch (Exception e) 314 { 315 // We'll just ignore this. 316 } 317 } 318 319 320 if (! targetFile.exists()) 321 { 322 break; 323 } 324 else 325 { 326 try 327 { 328 Thread.sleep(10); 329 } catch (InterruptedException ie) {} 330 } 331 } 332 333 if (outputFile != null) 334 { 335 try 336 { 337 outputFile.close(); 338 } 339 catch (Throwable t) {} 340 } 341 342 if (targetFile.exists()) 343 { 344 return EXIT_CODE_TIMEOUT; 345 } 346 else 347 { 348 return EXIT_CODE_SUCCESS; 349 } 350 } 351 } 352