blob: 5320364923da0ca06da64a96fee2c80b2adfebd9 [file] [log] [blame]
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
/*
* AutoDeployMonitor.java
*
* Created on May 11, 2004, 3:08 PM
*/
package autodeploy.test;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import org.glassfish.deployment.autodeploy.AutoDeployConstants;
/**
*Autodeploys an archive to the specified autodeploy directory.
*<p>
*To autodeploy the app, follow these steps:
*1. Record the modification time of the archive file in the autodeploy directory as the start time.
*2. Copy the archive to the autodeploy directory.
*3. Monitor the autodeploy directory until it contains a marker file (for either success or
* failure) with a creation date and time later than the earlier-recorded timestamp.
*4. Choose whether to return success or failure based on which kind of marker file has appeared
* in the autodeploy directory.
*
* @author tjquinn
*/
public class AutoDeployMonitor {
private static boolean DEBUG = Boolean.getBoolean("monitor.debug");
private static int ITERATION_LIMIT = Integer.getInteger("monitor.iterationLimit", 60 * 2 /* default = two minutes */).intValue();
private String archiveName = null;
// private String autodeployDirSpec = null;
private File autodeployDir = null;
// private String timestampFormat = null;
// private String timestampString = null;
private long timestamp;
private Date startTime = null;
private final static String LINE_SEP = System.getProperty("line.separator");
/** Creates a new instance of AutoDeployer */
public AutoDeployMonitor() {
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
int result = new AutoDeployMonitor().run(args);
System.exit(result);
}
private void processArguments(String[] args) {
if (args.length < 4) {
usage();
System.exit(1);
}
archiveName = args[0];
String autodeployDirSpec = args[1];
String timestampFormat = args[2];
String timestampString = args[3];
autodeployDir = new File(autodeployDirSpec);
debug("Archive to autodeploy: " + archiveName);
debug("Autodeploy directory: " + autodeployDir.getAbsolutePath());
StringBuffer result = new StringBuffer();
/*
*Check auto-deploy directory.
*/
if ( ! autodeployDir.exists()) {
result.append(LINE_SEP).append("Autodeploy directory " + autodeployDir.getAbsolutePath() + " does not exist but should.");
}
/*
*Check archive file name.
*/
if (archiveName.length() == 0) {
result.append(LINE_SEP).append("Archive file name must not be empty but is.");
}
/*
*Check the timestamp format and value.
*/
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(timestampFormat);
Date timestampDate = null;
try {
timestampDate = simpleDateFormat.parse(timestampString);
timestamp = timestampDate.getTime();
debug("Timestamp to use for filtering autodeploy status files: " + timestampDate.toString());
} catch (ParseException pe) {
result.append(LINE_SEP).append("Could not interpret timestamp " + timestampString + " using format " + timestampFormat).append(LINE_SEP).append(" ").append(pe.getMessage());
}
if (result.length() > 0) {
throw new IllegalArgumentException(result.toString());
}
}
private int run(String[] args) {
/*
*The calling script should pass these command line arguments:
*
*arg[0] archive file name and type
*arg[1] auto-deploy directory spec
*arg[2] SimpleDateFormat pattern to use in parsing the timestamp string
*arg[3] timestamp string
*
*/
try {
processArguments(args);
/*
*The timestamp handling allows the logic below to identify a marker file (..._deployed,
*..._undeployed, ..._deployFailed, ..._undeployFailed) that was created after the
*archive was deposited into (for autodeploy) or removed from (for autoundeploy) the
*autodeploy directory. We need to do this to make sure we do not accidentally take
*action on an old marker file that is still there because the autodeployer has not
*yet acted on the new file.
*/
/*
*For auto-deploy, the archive will have just been copied into the autodeploy directory.
*For auto-undeploy, the archive will have just been deleted from there. The file filter
*below uses both the file name and also a timestamp to make sure it accepts
*marker files created after the archive itself.
*
*Note that the following is both a declaration of the filter and its initialization by
*invoking its init method.
*/
FileFilter filter = new FileFilter () {
private long timestamp;
private String archiveName = null;
public boolean accept(File candidateFile) {
/*
*Make sure the name of the candidate starts with the name of the archive and that
*the candidate is no older than the archive file. Make sure it's one of the marker
*file types we're interested in.
*/
String candidateFileSpec = candidateFile.getAbsolutePath();
long candidateTimestamp = candidateFile.lastModified();
String candidateNameAndType = candidateFileSpec.substring(candidateFileSpec.lastIndexOf(File.separator) + 1);
String candidateType = candidateFileSpec.substring(candidateFileSpec.lastIndexOf('.') + 1);
boolean answer = (candidateTimestamp > this.timestamp)
&& (candidateNameAndType.equals(archiveName + AutoDeployConstants.DEPLOYED) ||
candidateNameAndType.equals(archiveName + AutoDeployConstants.UNDEPLOYED) ||
candidateNameAndType.equals(archiveName + AutoDeployConstants.DEPLOY_FAILED) ||
candidateNameAndType.equals(archiveName + AutoDeployConstants.UNDEPLOY_FAILED)
);
if (DEBUG) {
Date candidateTimestampDate = new Date(candidateTimestamp);
debug("Result of filtering file " + candidateFileSpec + " with modification date " + candidateTimestampDate.toString() + " : " + answer);
}
return answer;
}
public FileFilter init(String archiveName, long timestamp) {
this.archiveName = archiveName;
this.timestamp = timestamp;
return this;
}
}.init(archiveName, timestamp);
File [] matches = null;
/*
*Begin waiting for a new marker file to appear in the autodeploy directory. Don't wait longer than
*two minutes (by default) in case there is some problem.
*/
int iterationCount = 0;
do {
debug("Starting polling iteration " + iterationCount + "...");
Thread.currentThread().sleep(1000);
/*
*List the files that have the same name as the archive but are not the archive itself.
*This should mean we get only the marker file(s) for this archive.
*/
matches = autodeployDir.listFiles(filter);
} while ( (matches.length == 0) && (iterationCount++ < ITERATION_LIMIT));
/*
*Return 0 if the marker file found ends with _deployed, 1 if the marker ends with
*_deployFailed, and -1 otherwise.
*/
if (DEBUG) {
System.out.println("Matched files:");
for (int i = 0; i < matches.length; i++) {
System.out.println(" " + matches[i].getAbsolutePath());
}
}
String matchFileSpec = matches[0].getAbsolutePath();
int answer = -1;
if (matchFileSpec.endsWith(AutoDeployConstants.DEPLOYED) || matchFileSpec.endsWith(AutoDeployConstants.UNDEPLOYED)) {
answer = 0;
debug("Found successful marker file: " + matchFileSpec);
} else if (matchFileSpec.endsWith(AutoDeployConstants.DEPLOY_FAILED) || matchFileSpec.endsWith(AutoDeployConstants.UNDEPLOY_FAILED)) {
answer = 1;
debug("Found unsuccessful marker file: " + matchFileSpec);
} else {
debug("Found no marker file at all");
}
return answer;
} catch (Throwable thr) {
System.err.println("Error monitoring autodeployment/autoundeployment");
thr.printStackTrace();
return -1;
}
}
private void usage() {
System.err.println("Usage:");
System.err.println(" autodeploy.loader.client.AutoDeployMonitor <archive-name> <autodeploy-directory> <SimpleDateFormat-pattern-for-timestamp> <timestamp-value>");
}
private void debug(String msg) {
if (DEBUG) {
System.out.println(msg);
}
}
}