extensions/net.sf.basedb.relax/trunk/src/net/sf/basedb/relax/plugins/ScriptWriter.java

Code
Comments
Other
Rev Date Author Line
4577 19 Sep 17 nicklas 1 package net.sf.basedb.relax.plugins;
4577 19 Sep 17 nicklas 2
5250 18 Jan 19 nicklas 3 import java.io.ByteArrayOutputStream;
4577 19 Sep 17 nicklas 4 import java.io.IOException;
5250 18 Jan 19 nicklas 5 import java.io.InputStream;
4577 19 Sep 17 nicklas 6 import java.io.OutputStreamWriter;
4577 19 Sep 17 nicklas 7 import java.io.Writer;
4577 19 Sep 17 nicklas 8 import java.nio.charset.Charset;
4577 19 Sep 17 nicklas 9 import java.util.Date;
4577 19 Sep 17 nicklas 10 import java.util.Map;
4577 19 Sep 17 nicklas 11 import java.util.Set;
4577 19 Sep 17 nicklas 12 import java.util.TreeMap;
4577 19 Sep 17 nicklas 13 import java.util.TreeSet;
4577 19 Sep 17 nicklas 14
4577 19 Sep 17 nicklas 15 import org.json.simple.JSONArray;
4577 19 Sep 17 nicklas 16 import org.json.simple.JSONObject;
4577 19 Sep 17 nicklas 17
4577 19 Sep 17 nicklas 18 import net.sf.basedb.core.DbControl;
4577 19 Sep 17 nicklas 19 import net.sf.basedb.core.FileServer;
4577 19 Sep 17 nicklas 20 import net.sf.basedb.core.plugin.ExportOutputStream;
4577 19 Sep 17 nicklas 21 import net.sf.basedb.opengrid.ScriptBuilder;
4577 19 Sep 17 nicklas 22 import net.sf.basedb.relax.Relax;
4608 03 Oct 17 nicklas 23 import net.sf.basedb.relax.ServerMode;
4577 19 Sep 17 nicklas 24 import net.sf.basedb.relax.bash.ScriptUtil;
4577 19 Sep 17 nicklas 25 import net.sf.basedb.relax.dao.Fileserver;
4577 19 Sep 17 nicklas 26 import net.sf.basedb.util.FileUtil;
4577 19 Sep 17 nicklas 27
4577 19 Sep 17 nicklas 28 /**
4577 19 Sep 17 nicklas 29   A special writer implementation for creating bash scripts
4577 19 Sep 17 nicklas 30   intended to be executed manually in order to sync released
4577 19 Sep 17 nicklas 31   data files between the release-archive and level3-archive.
4577 19 Sep 17 nicklas 32   
4577 19 Sep 17 nicklas 33   Three scripts are created:
4577 19 Sep 17 nicklas 34   
4577 19 Sep 17 nicklas 35   * mkdirs.sh: Creates the directory structure that is needed for the release
4577 19 Sep 17 nicklas 36   * rsync.sh: Copy files from the release archive to the level 3 archive
4577 19 Sep 17 nicklas 37   
4577 19 Sep 17 nicklas 38   @author nicklas
4577 19 Sep 17 nicklas 39 */
4577 19 Sep 17 nicklas 40 public class ScriptWriter 
4577 19 Sep 17 nicklas 41 {
4577 19 Sep 17 nicklas 42
4577 19 Sep 17 nicklas 43   private final FileServer releaseArchive;
4577 19 Sep 17 nicklas 44   private final ReleaseWriterOptions options;
4577 19 Sep 17 nicklas 45
4577 19 Sep 17 nicklas 46   private final Set<String> pathsToCreate;
4577 19 Sep 17 nicklas 47   private final Map<String, String> filesToSync;
4577 19 Sep 17 nicklas 48
4577 19 Sep 17 nicklas 49   public ScriptWriter(DbControl dc, ReleaseWriterOptions options) 
4577 19 Sep 17 nicklas 50   {
4608 03 Oct 17 nicklas 51     this.releaseArchive = Relax.getServerMode() == ServerMode.RELAX ? Fileserver.RELEASE_ARCHIVE.load(dc) : Fileserver.LEVEL3_ARCHIVE.load(dc);
4577 19 Sep 17 nicklas 52     this.pathsToCreate = new TreeSet<>();
4577 19 Sep 17 nicklas 53     this.filesToSync = new TreeMap<>();
4577 19 Sep 17 nicklas 54     this.options = options;
4577 19 Sep 17 nicklas 55   }
4577 19 Sep 17 nicklas 56
4577 19 Sep 17 nicklas 57   /**
4577 19 Sep 17 nicklas 58     Add a directory that should be created as part of this release.
4577 19 Sep 17 nicklas 59   */
4577 19 Sep 17 nicklas 60   public void addMkDir(String path)
4577 19 Sep 17 nicklas 61   {
4577 19 Sep 17 nicklas 62     if (path != null) 
4577 19 Sep 17 nicklas 63     {
4577 19 Sep 17 nicklas 64       ScriptUtil.checkValidPath(path, true, false);
4577 19 Sep 17 nicklas 65       pathsToCreate.add(path);
4577 19 Sep 17 nicklas 66     }
4577 19 Sep 17 nicklas 67   }
4577 19 Sep 17 nicklas 68   
4577 19 Sep 17 nicklas 69   /**
4577 19 Sep 17 nicklas 70     Add files that are part of this release. The given path
4577 19 Sep 17 nicklas 71     is automatically added to {@link #addMkDir(String)}.
4577 19 Sep 17 nicklas 72     The list of files will checked with {@link OutputLocation#findReleasedFile(String)}
4577 19 Sep 17 nicklas 73     to determine if a symbolic link should be created or if the file should be 
4577 19 Sep 17 nicklas 74     copied from the project archive.
4577 19 Sep 17 nicklas 75     
4577 19 Sep 17 nicklas 76     @param releasePath Path on the release server
4577 19 Sep 17 nicklas 77      @param jsonFiles
4577 19 Sep 17 nicklas 78   */
4577 19 Sep 17 nicklas 79   public void addFiles(String releasePath, JSONArray jsonFiles)
4577 19 Sep 17 nicklas 80   {
4577 19 Sep 17 nicklas 81     addMkDir(releasePath);
4577 19 Sep 17 nicklas 82     
4577 19 Sep 17 nicklas 83     if (!releasePath.endsWith("/")) releasePath += "/";
4577 19 Sep 17 nicklas 84     
4577 19 Sep 17 nicklas 85     for (int fileNo = 0; fileNo < jsonFiles.size(); fileNo++)
4577 19 Sep 17 nicklas 86     {
4577 19 Sep 17 nicklas 87       JSONObject jsonFile = (JSONObject)jsonFiles.get(fileNo);
4577 19 Sep 17 nicklas 88       String filename = (String)jsonFile.get("name");
4577 19 Sep 17 nicklas 89       String sourcePath = (String)jsonFile.get("path");
4577 19 Sep 17 nicklas 90       if (sourcePath != null && filename != null)
4577 19 Sep 17 nicklas 91       {
4577 19 Sep 17 nicklas 92         // The path to this file in the release directory
4577 19 Sep 17 nicklas 93         String pathToReleaseFile = releasePath + ScriptUtil.checkValidFilename(filename);
4577 19 Sep 17 nicklas 94         String pathToOriginalFile = ScriptUtil.checkValidPath(sourcePath, false, false);
4577 19 Sep 17 nicklas 95         filesToSync.put(pathToReleaseFile, pathToOriginalFile);
4577 19 Sep 17 nicklas 96       }
4577 19 Sep 17 nicklas 97     }
4577 19 Sep 17 nicklas 98   }
4577 19 Sep 17 nicklas 99   
4577 19 Sep 17 nicklas 100   public void writeScripts(FileServerOutputLocation location)
4577 19 Sep 17 nicklas 101   {
5250 18 Jan 19 nicklas 102     ScriptBuilder releaseInfo = new ScriptBuilder();
5250 18 Jan 19 nicklas 103     addScriptInfo(releaseInfo);
5250 18 Jan 19 nicklas 104     
4577 19 Sep 17 nicklas 105     /* MKDIRS */
5250 18 Jan 19 nicklas 106     String mkdirs = getTextFile("/net/sf/basedb/relax/bash/mkdirs-template.sh");    
5250 18 Jan 19 nicklas 107     mkdirs = mkdirs.replace("<<RELEASEINFO>>", releaseInfo.toString());
5250 18 Jan 19 nicklas 108     mkdirs = mkdirs.replace("<<NUMPATHS>>", Integer.toString(pathsToCreate.size()));
5250 18 Jan 19 nicklas 109     ScriptBuilder createPath = new ScriptBuilder();
4577 19 Sep 17 nicklas 110     for (String path : pathsToCreate)
4577 19 Sep 17 nicklas 111     {
4577 19 Sep 17 nicklas 112       if (!path.startsWith("/")) path = "/" + path;
5250 18 Jan 19 nicklas 113       createPath.cmd("createPath \"" + path + "\"");
4577 19 Sep 17 nicklas 114     }
5250 18 Jan 19 nicklas 115     mkdirs = mkdirs.replace("<<SCRIPT>>", createPath.toString());
5250 18 Jan 19 nicklas 116     writeScript(location, "/mkdirs.sh", mkdirs);
4577 19 Sep 17 nicklas 117
4577 19 Sep 17 nicklas 118     /* RSYNC */
5250 18 Jan 19 nicklas 119     String rsync = getTextFile("/net/sf/basedb/relax/bash/rsync-template.sh");
5250 18 Jan 19 nicklas 120     rsync = rsync.replace("<<RELEASEINFO>>", releaseInfo.toString());
5250 18 Jan 19 nicklas 121     rsync = rsync.replace("<<NUMFILES>>", Integer.toString(filesToSync.size()));
5250 18 Jan 19 nicklas 122     
4770 18 Apr 18 nicklas 123     String releaseArchiveHost = releaseArchive.getHost();
4770 18 Apr 18 nicklas 124     String releaseArchivePortOption = "";
4770 18 Apr 18 nicklas 125     if (releaseArchiveHost.contains(":"))
4770 18 Apr 18 nicklas 126     {
4770 18 Apr 18 nicklas 127       int i = releaseArchiveHost.lastIndexOf(':');
4770 18 Apr 18 nicklas 128       releaseArchivePortOption = " -e 'ssh -p " + ScriptUtil.checkValidScriptParameter(releaseArchiveHost.substring(i+1)) + "'";
4770 18 Apr 18 nicklas 129       releaseArchiveHost = releaseArchiveHost.substring(0, i);
4770 18 Apr 18 nicklas 130     }
5250 18 Jan 19 nicklas 131     
4770 18 Apr 18 nicklas 132     ScriptUtil.checkValidScriptParameter(releaseArchiveHost);
4577 19 Sep 17 nicklas 133     String releaseArchivePath = ScriptUtil.checkValidPath(releaseArchive.getRootPath(), true, false);
5250 18 Jan 19 nicklas 134     
5250 18 Jan 19 nicklas 135     rsync = rsync.replace("<<RSYNCOPTIONS>>", "-aiL"+releaseArchivePortOption);
5250 18 Jan 19 nicklas 136     rsync = rsync.replace("<<DEFAULTRELEASEARCHIVE>>", releaseArchiveHost + ":" + releaseArchivePath);
5250 18 Jan 19 nicklas 137     ScriptBuilder syncFile = new ScriptBuilder();
4577 19 Sep 17 nicklas 138     for (Map.Entry<String, String> entry : filesToSync.entrySet())
4577 19 Sep 17 nicklas 139     {
4577 19 Sep 17 nicklas 140       String destPath = entry.getKey();
4577 19 Sep 17 nicklas 141       String srcPath = entry.getValue();
5250 18 Jan 19 nicklas 142       syncFile.cmd("syncFile \"" + srcPath + "\" \""+destPath + "\"");
4577 19 Sep 17 nicklas 143     }
5250 18 Jan 19 nicklas 144     rsync = rsync.replace("<<SCRIPT>>", syncFile.toString());
4577 19 Sep 17 nicklas 145     writeScript(location, "/rsync.sh", rsync.toString());
4577 19 Sep 17 nicklas 146   }
4577 19 Sep 17 nicklas 147   
4577 19 Sep 17 nicklas 148   private void writeScript(FileServerOutputLocation location, String scriptPath, String script)
4577 19 Sep 17 nicklas 149   {
4577 19 Sep 17 nicklas 150     ExportOutputStream out = null;
4577 19 Sep 17 nicklas 151     try
4577 19 Sep 17 nicklas 152     {
4577 19 Sep 17 nicklas 153       out = location.getOutputStream(scriptPath, true);
4577 19 Sep 17 nicklas 154       out.setCharacterSet("UTF-8");
4577 19 Sep 17 nicklas 155       out.setMimeType("text/x-shellscript");
4577 19 Sep 17 nicklas 156       Writer writer = new OutputStreamWriter(out, Charset.forName("UTF-8"));
4577 19 Sep 17 nicklas 157       writer.write(script);
4577 19 Sep 17 nicklas 158       writer.flush();
4577 19 Sep 17 nicklas 159       out.flush();
4577 19 Sep 17 nicklas 160       writer.close();
4577 19 Sep 17 nicklas 161     }
4577 19 Sep 17 nicklas 162     catch (IOException ex)
4577 19 Sep 17 nicklas 163     {
4577 19 Sep 17 nicklas 164       throw new RuntimeException(ex);
4577 19 Sep 17 nicklas 165     }
4577 19 Sep 17 nicklas 166     finally
4577 19 Sep 17 nicklas 167     {
4577 19 Sep 17 nicklas 168       FileUtil.close(out);
4577 19 Sep 17 nicklas 169     }
4577 19 Sep 17 nicklas 170
4577 19 Sep 17 nicklas 171   }
4577 19 Sep 17 nicklas 172   
4577 19 Sep 17 nicklas 173   private void addScriptInfo(ScriptBuilder script)
4577 19 Sep 17 nicklas 174   {
4577 19 Sep 17 nicklas 175     script.comment("Created by : Relax " + Relax.VERSION);
4577 19 Sep 17 nicklas 176     script.comment("Created at : " + Relax.CONVERTER_DATETIME_TO_STRING_WITH_SEPARATOR.convert(new Date()));
4577 19 Sep 17 nicklas 177     script.comment("Item list  : " + options.getList().getName());
4577 19 Sep 17 nicklas 178     script.comment("Release    : " + options.getVersion());
4577 19 Sep 17 nicklas 179     script.comment("");
4577 19 Sep 17 nicklas 180   }
4577 19 Sep 17 nicklas 181   
5250 18 Jan 19 nicklas 182   private String getTextFile(String path)
5250 18 Jan 19 nicklas 183   {
5250 18 Jan 19 nicklas 184     String readme = null;
5250 18 Jan 19 nicklas 185     InputStream in = null;
5250 18 Jan 19 nicklas 186     ByteArrayOutputStream buffer = new ByteArrayOutputStream(2048);
5250 18 Jan 19 nicklas 187     try
5250 18 Jan 19 nicklas 188     {
5250 18 Jan 19 nicklas 189       in = getClass().getResourceAsStream(path);
5250 18 Jan 19 nicklas 190       FileUtil.copy(in, buffer);
5250 18 Jan 19 nicklas 191       readme = buffer.toString("UTF-8");
5250 18 Jan 19 nicklas 192     }
5250 18 Jan 19 nicklas 193     catch (IOException ex)
5250 18 Jan 19 nicklas 194     {
5250 18 Jan 19 nicklas 195       throw new RuntimeException(ex);
5250 18 Jan 19 nicklas 196     }
5250 18 Jan 19 nicklas 197     finally
5250 18 Jan 19 nicklas 198     {
5250 18 Jan 19 nicklas 199       FileUtil.close(in);
5250 18 Jan 19 nicklas 200     }
5250 18 Jan 19 nicklas 201     return readme;
5250 18 Jan 19 nicklas 202   }
5250 18 Jan 19 nicklas 203
4577 19 Sep 17 nicklas 204 }