/*
* [DistributeAuxAndJNLP.java]
*
* Summary: Prepares aux files such as the JNLP files ready to be uploaded to the website.
*
* Copyright: (c) 2003-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
*
* Licence: This software may be copied and used freely for any purpose but military.
* http://mindprod.com/contact/nonmil.html
*
* Requires: JDK 1.8+
*
* Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
*
* Version History:
* 6.4 2004-04-04 regenerate date embeded in jnlp files to
* foil untouch. It was needlessly regenerating jnlp files over
* and over since untouch redated them back to look too old.
*/
package com.mindprod.replicatorsender;
import com.mindprod.common18.Build;
import com.mindprod.common18.EIO;
import com.mindprod.common18.Localise;
import com.mindprod.fastcat.FastCat;
import com.mindprod.replicatorcommon.Config;
import com.mindprod.replicatorcommon.IO;
import com.mindprod.replicatorcommon.MiniFD;
import com.mindprod.replicatorcommon.ReplicatorCommon;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.zip.GZIPOutputStream;
import static com.mindprod.replicatorsender.ConfigForSender.*;
import static java.lang.System.*;
/**
* Prepares aux files such as the JNLP files ready to be uploaded to the website.
*
* Prepare files for distribution to the client, other than the zips
* and the zip manifest. e.g. replicator.icon64.gif, replicator.jnlp,
* (*).jnlp, replicator.jar
*
* @author Roedy Green, Canadian Mind Products
* @version 6.4 2004-04-04 regenerate date embedded in jnlp files to
* foil untouch. It was needlessly regenerating jnlp files over
* and over since untouch redated them back to look too old.
* @since 2003-10-05
*/
final class DistributeAuxAndJNLP
{
/**
* We round published file sizes to multiples of this number. Does not have to be a power of two.
*/
private static final int ROUND_TO = 16 * 1024;
/**
* field ending for non-paired field
*/
private static final String FE = " />\n";
/**
* Time NOW_STRING, sampled only once so all files will be dated consistently. mask for: 2005-01-20 23:59 GMT
*/
private static final String NOW_STRING =
new SimpleDateFormat( "yyyy-MM-dd HH:mm zz" )
.format( new Date() );
/**
* Timestamp that means generated files are considered fresh. Any older than this and they will be regenerated.
*/
private static long freshDate;
/**
* Sanity check. Ensure crucial files are present sender sender zip staging direectory
*/
static void auxRollCall()
{
try
{
// xxxreplicator.properties should be in E:\com\mindprod\replicatorsender
// It must be there, or we could not have got started.
// presume current dir in E:\com\mindprod\replicatorsender
IO.ensureFileExists( new File( "replicatorsender.jar" ) );
// these should exist in E:\mindprod\replicator
// We don't copy them in from anywhere. Should be manually placed
// using prop.bat no longer use any *.gif files.
final String[] crucialFiles = {
"autorun.inf",
Config.CODE_SIGNING_CERT + ".cer",
"replicator.icon64.png",
"replicator.ico",
"replicator.jar",
"replicator.splash.png",
"setup.exe" };
for ( String crucialFile : crucialFiles )
{
IO.ensureFileExists( new File( SENDER_ZIP_STAGING_DIR, crucialFile ) );
}
}
catch ( IOException e )
{
ReplicatorCommon.fatal( e.getMessage()
+ "\n"
+ "Current directory: "
+ IO.getCurrentDir() );
}
}
/**
* Calculate the timestamp that means generated files are considered fresh. Any older than this and they will be
* regenerated.
*/
private static void calcFreshDate()
{
final long propertiesDate = new File( PROPERTIES_FILE )
.lastModified();
final long receiverDate =
new File( SENDER_ZIP_STAGING_DIR, "replicator.jar" ).lastModified();
// 0 if file missing.
// replicatorsender.jar is not in staging dir.
freshDate = Math.max( propertiesDate, receiverDate );
}
/**
* distribute freshness.ser to help client decide which files it needs to download.
*/
private static void distributeFreshness()
{
// zipmanifest.ser not included. It's timestamp is not yet known.
out.println( Localise.localise( "regenerating " + Config.FRESHNESS_SER ) );
// aux files we distribute as well that live int the replicator
// directory
final String[] auxFiles = {
"autorun.inf",
Config.CODE_SIGNING_CERT + ".cer",
"replicator.icon64.png",
"replicator.splash.png",
"replicator.ico",
"replicator.jar",
"replicatorreceiverlan.jnlp",
"replicatorreceiverrelay.jnlp",
"replicatorreceiverwebsite.jnlp",
"setup.exe" };
// don't distribute replicatorreceivertest.jnlp
final ArrayList distributeAlso =
new ArrayList<>( auxFiles.length + 26 );
for ( String auxFile : auxFiles )
{
final MiniFD fd = new MiniFD( "", auxFile );
final File f = new File( SENDER_ZIP_STAGING_DIR, auxFile );
fd.setClumping( f.lastModified() );
distributeAlso.add( fd );
}
// handle all the replicatorreceivercdX.jnlp files
for ( char driveLetter = 'A'; driveLetter <= 'Z'; driveLetter++ )
{
final MiniFD fd =
new MiniFD( "",
"replicatorreceivercd"
+ driveLetter
+ ".jnlp"
);
final File f =
new File( SENDER_ZIP_STAGING_DIR,
"replicatorreceivercd" + driveLetter + ".jnlp" );
fd.setClumping( f.lastModified() );
distributeAlso.add( fd );
}
final String freshnessFilename = SENDER_ZIP_STAGING_DIR + File
.separatorChar + Config
.FRESHNESS_SER;
try
{
final FileOutputStream fos =
new FileOutputStream( freshnessFilename );
final GZIPOutputStream gzos =
new GZIPOutputStream( fos, 4 * 1024/* buffsize */ );
final ObjectOutputStream oos = new ObjectOutputStream( gzos );
oos.writeObject( distributeAlso.toArray( new MiniFD[ distributeAlso
.size() ] ) );
oos.close();
}
catch ( IOException e )
{
ReplicatorCommon.fatal( "Unable to save "
+ freshnessFilename
+ " file."
+ "\n"
+ e.getMessage() );
}
}
/**
* Generate jnlp file directly in sender staging dir.
*
* @param via VIA_WEBSITE VIA_LAN VIA_RELAY VIA_TEST VIA_CD
* @param driveLetter e.g. R drive letter for CDROM, in caps.
*/
private static void distributeJNLP( ViaForSender via, char driveLetter )
{
final String jnlpName = via.getJnlpName( driveLetter );
final String codebase = via.getCodebase( driveLetter );
final boolean keepZips = via.defaultKeepZips();
final boolean unpackZips = via.defaultUnpackZips();
final String authentication = via.getAuthentication();
final boolean offlineAllowed = via.isOfflineAllowed();
try
{
// O P E N
final File jnlpFile = new File( SENDER_ZIP_STAGING_DIR, jnlpName );
// don't regenerate the jnlp file unless it will change.
if ( jnlpFile.exists() && jnlpFile.lastModified() > freshDate )
{
return;
}
out.println( "regenerating " + jnlpName );
final PrintWriter prw = EIO.getPrintWriter( jnlpFile, 4 * 1024, EIO.UTF8 );
// round to make it more stable.
final long jarSize = ( ( new File( ConfigForSender.SENDER_ZIP_STAGING_DIR,
"replicator.jar" ).length() + ROUND_TO / 2 ) / ROUND_TO ) * ROUND_TO;
// W R I T E
final FastCat sb = new FastCat( 170 );
sb.append( "\n" );
sb.append( "\n" );
sb.append( "\n" );
// sb.append( "\n" );
// sb.append( "\n" );
sb.append( "\n" );
sb.append( " \n" );
sb.append( " The Replicator " );
sb.append( Config.VERSION );
sb.append( " via " );
sb.append( via );
sb.append( "\n" );
sb.append( "\n" );
sb.append( " Canadian Mind Products\n" );
sb.append( " Replicates files " );
sb.append( via.getDescription() );
sb.append( ". Also keeps them up to date efficiently." );
sb.append( "\n" );
sb.append( " Replicates files " );
sb.append( via.getDescription() );
sb.append( ".\n" );
sb.append( " Replicates files " );
sb.append( via.getDescription() );
sb.append( ".\n" );
sb.append( " the Replicator\n" );
sb.append( " \n" );
sb.append( " " );
sb.append( "\n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( "\n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( "\n" );
sb.append( " \n" );
sb.append( "\n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( "\n" );
sb.append( " \n" );
sb.append( " \n" );
sb.append( "\n" );
prw.write( sb.toString() );
// C L O S E
prw.close();
}
catch ( IOException e )
{
ReplicatorCommon.fatal( "Unable to create "
+ jnlpName
+ "\n"
+ e.getMessage() );
}
}
/**
* Generate startover.bat to start over in E:\com\mindprod\replicatorsender
*/
private static void distributeStartOver()
{
try
{
// presume current directory is E:\com\mindprod\replicatorsender
// O P E N
final File batfile = new File( "startover.bat" );
// don't regenerate the bat file unless it will change.
if ( batfile.exists() && batfile.lastModified() > freshDate )
{
return;
}
out.println( "regenerating startover.bat" );
final PrintWriter prw = EIO.getPrintWriter( batfile, 4 * 1024, EIO.UTF8 );
// W R I T E
final FastCat sb = new FastCat( 125 );
sb.append( "@echo off\n" );
sb.append( "rem startOver.bat start from scratch\n" );
sb.append( "rem this runs only under Windows. You will need to convert to other OSes.\n" );
sb.append( "rem may be run from any directory\n" );
sb.append( "rem last regenerated " );
sb.append( NOW_STRING );
sb.append( "\n" );
sb.append( "if not exist " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceiverwebsite.jnlp " );
sb.append( "echo missing " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceiverwebsite.jnlp\n" );
sb.append( "echo About to start The Replicator over from scratch, To abort, hit Ctrl-C now.\n" );
sb.append( "pause\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\" );
sb.append( Config.FRESHNESS_SER );
sb.append( "\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\" );
sb.append( Config.ZIPDETAILEDMANIFEST_SER );
sb.append( "\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\" );
sb.append( Config.ZIPMANIFEST_SER );
sb.append( "\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceivercd*.jnlp\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceiverlan.jnlp\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceiverrelay.jnlp\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceivertest.jnlp\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\replicatorreceiverwebsite.jnlp\n" );
sb.append( "del " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\\z*.zip\n" );
sb.append( "del " );
sb.append( SENDER_PERSIST_DIR );
sb.append( "\\" );
sb.append( SENDER_SER );
sb.append( "\n" );
sb.append( "del " );
sb.append( SENDER_PERSIST_DIR );
sb.append( "\\" );
sb.append( SENDER_LOG );
sb.append( "\n" );
//
// replace files that won't be regenerated
//
sb.append( "copy " );
sb.append( SENDER_PERSIST_DIR );
sb.append( "\\autorun.inf " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "copy " );
sb.append( SENDER_PERSIST_DIR );
sb.append( "\\" );
sb.append( Config.CODE_SIGNING_CERT );
sb.append( ".cer " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "copy " );
sb.append( SENDER_PERSIST_DIR );
sb.append( "\\setup.exe " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "copy " );
sb.append( REPLICATOR_SOURCE_DIR );
sb.append( "\\replicator.ico " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "copy " );
sb.append( REPLICATOR_SOURCE_DIR );
sb.append( "\\replicator.jar " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "copy " );
sb.append( REPLICATOR_SOURCE_DIR );
sb.append( "\\replicator.icon64.png " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "copy " );
sb.append( REPLICATOR_SOURCE_DIR );
sb.append( "\\replicator.splash.png " );
sb.append( SENDER_ZIP_STAGING_DIR );
sb.append( "\n" );
sb.append( "rem -30-\n" );
prw.print( sb.toString() );
// C L O S E
prw.close();
}
catch ( IOException e )
{
ReplicatorCommon.fatal( "Unable to create startover.bat file."
+ "\n"
+ e.getMessage() );
}
}
/**
* Prepare files for distribution to the client, other than the zips and the zip manifest. e.g.
* replicator.icon64.gif, replicatorreceiver.jnlp, complexreplicatorreceiver.jnlp, replicator.jar
*/
public static void distribute()
{
// calc freshDate that lets know when files are stale and need to be
// regenerated.
calcFreshDate();
// distribute four types of jnlp file, put directly in sender staging
// dir
distributeJNLP( ViaForSender.VIA_WEBSITE, ' ' );
distributeJNLP( ViaForSender.VIA_LAN, ' ' );
distributeJNLP( ViaForSender.VIA_RELAY, ' ' );
distributeJNLP( ViaForSender.VIA_TEST, ' ' );
// arrgh. Have to generate a different jnlp file for possible CD drive
// letter.
for ( char driveLetter = 'A'; driveLetter <= 'Z'; driveLetter++ )
{
distributeJNLP( ViaForSender.VIA_CD, driveLetter );
}
// put startover.bat in E:\com\mindprod\replicatorsender
distributeStartOver();
// create file of freshness dates of all auxiliary files
// generate directly into sender staging directory
distributeFreshness();
// block untouch
//noinspection ResultOfMethodCallIgnored
new File( SENDER_ZIP_STAGING_DIR, "untouch.digest" )
.delete();
}
}