001/*
002 * #%L
003 * Netarchivesuite - deploy
004 * %%
005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023package dk.netarkivet.deploy;
024
025import java.io.File;
026import java.io.IOException;
027import java.io.PrintWriter;
028import java.util.HashMap;
029import java.util.Iterator;
030import java.util.LinkedHashMap;
031import java.util.Map;
032import java.util.Map.Entry;
033
034import org.dom4j.Element;
035
036import dk.netarkivet.common.exceptions.IOFailure;
037import dk.netarkivet.common.utils.FileUtils;
038
039/**
040 * A LinuxMachine is the instance of the abstract machine class, which runs the operating system Linux or another Unix
041 * dependent operation system. This class only contains the operating system specific functions.
042 */
043public class LinuxMachine extends Machine {
044
045        public static final String HERITRIX_1_CLASSNAME = "org.archive.crawler.Heritrix";
046
047    protected LinkedHashMap<String, String> bundles = new LinkedHashMap<>();
048        protected LinkedHashMap<String, String> certificates = new LinkedHashMap<String, String>();
049
050        /**
051     * The constructor. Starts by initialising the parent abstract class, then sets the operating system dependent
052     * variables.
053     *
054     * @param subTreeRoot The XML root element.
055     * @param parentSettings The Settings to be inherited from the PhysicalLocation, where this machine is placed.
056     * @param param The machine parameters to be inherited from the PhysicalLocation.
057     * @param netarchiveSuiteSource The name of the NetarchiveSuite package file. Must end with '.zip'.
058     * @param securityPolicy The security policy file, to be copied into machine directory.
059     * @param dbFile The name of the database file.
060     * @param arcdbFile The name of the archive file.
061     * @param resetDir Whether the temporary directory should be reset.
062     * @param externalJarFolder The folder containing the external jar library files.
063     * @param logoFile user specific logo png file.
064     * @param menulogoFile user specific menulogo png file.
065     * @param deployConfiguration The general deployment configuration.
066     * @param bitmagDir The folder containing the bitmagasin configuration.
067     */
068    public LinuxMachine(Element subTreeRoot, XmlStructure parentSettings, Parameters param,
069            String netarchiveSuiteSource, File slf4JConfig, File securityPolicy, File dbFile,
070            File arcdbFile, boolean resetDir, File externalJarFolder, File logoFile, File menulogoFile,
071            DeployConfiguration deployConfiguration, File bitmagDir) {
072        super(subTreeRoot, parentSettings, param, netarchiveSuiteSource, slf4JConfig, securityPolicy, dbFile,
073                arcdbFile, resetDir, externalJarFolder, logoFile, menulogoFile, bitmagDir);
074        // set operating system
075        operatingSystem = Constants.OPERATING_SYSTEM_LINUX_ATTRIBUTE;
076        scriptExtension = Constants.SCRIPT_EXTENSION_LINUX;
077
078        String[] bundlesArr;
079        String[] certificatesArr;
080        String srcStr;
081        String dstStr;
082        int idx;
083        for (Application app : applications) {
084            if (app.isBundledHarvester()) {
085                bundlesArr = app.getSettingsValues(Constants.SETTINGS_HARVEST_HERITRIX3_BUNDLE_LEAF);
086                if ((bundlesArr == null || bundlesArr.length == 0)
087                        && deployConfiguration.getDefaultBundlerZip() != null) {
088                    bundlesArr = new String[] { deployConfiguration.getDefaultBundlerZip().getAbsolutePath() };
089                } else if ((bundlesArr == null || bundlesArr.length == 0 || bundlesArr[0].length()==0)
090                        && deployConfiguration.getDefaultBundlerZip() == null) {
091                    throw new IllegalArgumentException("A Heritrix bundler needs to be defined for H3 controllers, "
092                            + "either directly in the deploy configuration or from the command line with the -B option.");
093                }
094                certificatesArr = app.getSettingsValues(Constants.SETTINGS_HARVEST_HERITRIX3_CERTIFICATE_LEAF);
095                if (bundlesArr != null && bundlesArr.length > 0 && certificatesArr != null) {
096                    for (int i = 0; i < bundlesArr.length; ++i) {
097                        srcStr = bundlesArr[i];
098                        if (!bundles.containsKey(srcStr)) {
099                            idx = srcStr.lastIndexOf('/');
100                            if (idx != -1) {
101                                dstStr = srcStr.substring(idx + 1);
102                            } else {
103                                dstStr = srcStr;
104                            }
105                            dstStr = machineParameters.getInstallDirValue() + "/" + getEnvironmentName() + "/" + dstStr;
106                            bundles.put(srcStr, dstStr);
107                            System.out.println(srcStr + " -> " + dstStr);
108                        }
109                    }
110                    for (int i = 0; i < certificatesArr.length; ++i) {
111                        srcStr = certificatesArr[i];
112                        if (!certificates.containsKey(srcStr)) {
113                            idx = srcStr.lastIndexOf('/');
114                            if (idx != -1) {
115                                dstStr = srcStr.substring(idx + 1);
116                            } else {
117                                dstStr = srcStr;
118                            }
119                            dstStr = machineParameters.getInstallDirValue() + "/" + getEnvironmentName() + "/" + dstStr;
120                            certificates.put(srcStr, dstStr);
121                            System.out.println(srcStr + " -> " + dstStr);
122                        }
123                    }
124                    XmlStructure appSettings = app.getSettings();
125                    Element heritrixBundleElement =
126                            appSettings.getSubChild(Constants.SETTINGS_HARVEST_HERITRIX3_BUNDLE_LEAF);
127                    if (heritrixBundleElement == null) {
128                        appSettings.getSubChild(Constants.SETTINGS_HERITRIX3_BRANCH).addElement("bundle");
129                        heritrixBundleElement =
130                                appSettings.getSubChild(Constants.SETTINGS_HARVEST_HERITRIX3_BUNDLE_LEAF);
131                        heritrixBundleElement.setText((String)bundles.values().toArray()[0]);
132                    } else {
133                        heritrixBundleElement.setText(bundles.get(heritrixBundleElement.getText()));
134                    }
135                    Element h3KeystoreElement = appSettings
136                            .getSubChild(Constants.SETTINGS_HARVEST_HERITRIX3_CERTIFICATE_LEAF);
137                    if (h3KeystoreElement != null) {
138                        String h3KeystoreName = certificates.get(h3KeystoreElement.getText());
139                        if (h3KeystoreName != null) {
140                            h3KeystoreElement.setText(h3KeystoreName);
141                        }
142                    }
143                }
144            }
145        }
146    }
147
148    protected static final class osInstallScriptTpl {
149        protected static final String[] mainScript = {
150            // echo copying null.zip to:kb-test-adm-001.kb.dk
151            "echo copying ${netarchiveSuiteFileName} to:${name}",
152            // scp null.zip dev@kb-test-adm-001.kb.dk:/home/dev
153            "scp ${netarchiveSuiteFileName} ${machineUserLogin}:${installDirValue}",
154            // echo deleting dev@kb-test-adm-001.kb.dk:/home/dev/TEST/lib
155            "echo deleting ${machineUserLogin}:${installDirValue}/${environmentName}/lib",
156            // ssh dev@kb-test-adm-001.kb.dk rm -rf /home/dev/TEST/lib
157            "ssh ${machineUserLogin} \"rm -rf ${installDirValue}/${environmentName}/lib\"",
158            // echo unzipping null.zip at:kb-test-adm-001.kb.dk
159            "echo unzipping ${netarchiveSuiteFileName} at:${name}",
160            // ssh dev@kb-test-adm-001.kb.dk unzip -q -o /home/dev/null.zip -d /home/dev/TEST
161            "ssh ${machineUserLogin} \"unzip -q -o ${installDirValue}/${netarchiveSuiteFileName} -d ${installDirValue}/${environmentName}\"",
162            // update Logos.
163            "${osUpdateLogos}",
164            // create other directories.
165            "${osInstallScriptCreateDir}",
166            // echo preparing for copying of settings and scripts
167            "echo preparing for copying of settings and scripts",
168            // For overriding jmxremote.password give user all rights.
169            // ssh machine: "if [ -e conf/jmxremote.password ];
170            // then chmod u+rwx conf/jmxremote.password; fi; "
171            "ssh ${machineUserLogin} \" cd ~; if [ -e ${installDirValue}/${environmentName}/conf/jmxremote.password ]; then chmod u+rwx ${installDirValue}/${environmentName}/conf/jmxremote.password; fi; \"",
172            // For overriding jmxremote.access give user all rights.
173            // ssh machine: "if [ -e conf/jmxremote.access ];
174            // then chmod u+rwx conf/jmxremote.access; fi; "
175            "ssh ${machineUserLogin} \" cd ~; if [ -e ${installDirValue}/${environmentName}/conf/jmxremote.access ]; then chmod u+rwx ${installDirValue}/${environmentName}/conf/jmxremote.access; fi; \"",
176            // echo copying settings and scripts
177            "echo copying settings and scripts",
178            // scp -r kb-test-adm-001.kb.dk/* dev@kb-test-adm-001.kb.dk:/home/dev/TEST/conf/
179            "scp -r ${name}/* ${machineUserLogin}:${installDirValue}/${environmentName}/conf/",
180            // INSTALL EXTERNAL JAR FILES.
181            "${osInstallExternalJarFiles}",
182            // APPLY HARVEST DEFINITION DATABASE!
183            "${osInstallDatabase}",
184            // APPLY ARCHIVE DATABASE!
185            "${osInstallArchiveDatabase}",
186            // echo make scripts executable
187            "echo make scripts executable",
188            // Allow only user to be able to deal with these files
189            // (go=-rwx,u=+rwx) = 700.
190            // ssh dev@kb-test-adm-001.kb.dk "chmod 700 /home/dev/TEST/conf/*.sh "
191            "ssh ${machineUserLogin} \"chmod 700 ${installDirValue}/${environmentName}/conf/*.sh \"",
192            // HANDLE JMXREMOTE PASSWORD AND ACCESS FILE.
193            "${JMXremoteFilesCommand}",
194            // END OF SCRIPT
195            "${heritrix3Files}"
196        };
197        protected static final String scpFile = "scp ${srcFileName} ${machineUserLogin}:${dstFileName}";
198    }
199
200    @Override
201    protected String osInstallScript() {
202        Map<String, String> env = new HashMap<String, String>();
203        StringBuilder sb = new StringBuilder();
204        Iterator<Entry<String, String>> iter;
205        String tmpStr;
206        env.put("machineUserLogin", machineUserLogin());
207        iter = bundles.entrySet().iterator();
208        Entry<String, String> entry;
209        while (iter.hasNext()) {
210                entry = iter.next();
211                env.put("srcFileName", entry.getKey());
212            env.put("dstFileName", entry.getValue());
213            tmpStr = Template.untemplate(osInstallScriptTpl.scpFile, env, true);
214            if (sb.length() > 0) {
215                sb.append("\n");
216            }
217            sb.append(tmpStr);
218        }
219        iter = certificates.entrySet().iterator();
220        while (iter.hasNext()) {
221                entry = iter.next();
222                env.put("srcFileName", entry.getKey());
223            env.put("dstFileName", entry.getValue());
224            tmpStr = Template.untemplate(osInstallScriptTpl.scpFile, env, true);
225            if (sb.length() > 0) {
226                sb.append("\n");
227            }
228            sb.append(tmpStr);
229        }
230
231        env.clear();
232        env.put("netarchiveSuiteFileName", netarchiveSuiteFileName);
233        env.put("name", hostname);
234        env.put("machineUserLogin", machineUserLogin());
235        env.put("installDirValue", machineParameters.getInstallDirValue());
236        env.put("environmentName", getEnvironmentName());
237        env.put("osUpdateLogos", osUpdateLogos());
238        env.put("osInstallScriptCreateDir", osInstallScriptCreateDir());
239        env.put("osInstallExternalJarFiles", osInstallExternalJarFiles());
240        env.put("osInstallDatabase", osInstallDatabase());
241        env.put("osInstallArchiveDatabase", osInstallArchiveDatabase());
242        env.put("JMXremoteFilesCommand", getJMXremoteFilesCommand());
243        env.put("heritrix3Files", sb.toString());
244        String str = Template.untemplate(osInstallScriptTpl.mainScript, env, true, "\n");
245        return str;
246    }
247
248    protected static final class osKillScriptTpl {
249        protected static final String[] mainScript = {
250            "ssh ${machineUserLogin} \". /etc/profile; ${installDirValue}/${environmentName}/conf/killall.sh\";"
251        };
252    }
253
254    @Override
255    protected String osKillScript() {
256        Map<String, String> env = new HashMap<String, String>();
257        env.put("machineUserLogin", machineUserLogin());
258        env.put("environmentName", getEnvironmentName());
259        env.put("installDirValue", machineParameters.getInstallDirValue());
260        String str = Template.untemplate(osKillScriptTpl.mainScript, env, true, "\n");
261        return str;
262    }
263
264    protected static final class osStartScriptTpl {
265        protected static final String[] mainScript = {
266            "ssh ${machineUserLogin} \". /etc/profile;. ~/.bash_profile; ${installDirValue}/${environmentName}/conf/startall.sh; sleep 5; cat ${installDirValue}/${environmentName}/*.log\""
267        };
268    }
269
270    /**
271     * Creates the operation system specific starting script for this machine.
272     * <p>
273     * pseudo code: - ssh maclogin ". /etc/profile; conf/startall.sh; sleep 5; cat install/*.log"
274     * <p>
275     * where: maclogin = login for machine (username@machine). conf = path to /conf directory. install = path to install
276     * directory.
277     *
278     * @return Operation system specific part of the startscript.
279     */
280    @Override
281    protected String osStartScript() {
282        Map<String, String> env = new HashMap<String, String>();
283        env.put("machineUserLogin", machineUserLogin());
284        env.put("environmentName", getEnvironmentName());
285        env.put("installDirValue", machineParameters.getInstallDirValue());
286        String str = Template.untemplate(osStartScriptTpl.mainScript, env, true, "\n");
287        return str;
288    }
289
290    @Override
291    protected String getInstallDirPath() {
292        return machineParameters.getInstallDirValue() + Constants.SLASH + getEnvironmentName();
293    }
294
295    @Override
296    protected String getConfDirPath() {
297        return getInstallDirPath() + Constants.CONF_DIR_LINUX;
298    }
299
300    /**
301     * Creates the local path to the lib dir.
302     *
303     * @return The path to the lib dir for ssh.
304     */
305    protected String getLocalLibDirPath() {
306        return Constants.LIB_DIR_LINUX;
307    }
308
309    /**
310     * This function creates the script to kill all applications on this machine. The scripts calls all the kill script
311     * for each application. It also runs the script for killing any external database.
312     * <p>
313     * pseudo code: - echo Killing all applications at machine: mac - if [ -e ./kill_app.sh ] - ./kill_app.sh - fi - ...
314     * <p>
315     * where: mac = machine name. app = application name. ... = the same for other applications.
316     *
317     * @param directory The directory for this machine (use global variable?).
318     * @throws IOFailure If an error occurred during the creation of the local killall script.
319     */
320    @Override
321    protected void createOSLocalKillAllScript(File directory) throws IOFailure {
322        // create the kill all script file
323        File killAllScript = new File(directory, Constants.SCRIPT_NAME_KILL_ALL + scriptExtension);
324        try {
325            // Initialise script
326            PrintWriter killPrinter = new PrintWriter(killAllScript, getTargetEncoding());
327            try {
328                killPrinter.println(ScriptConstants.ECHO_KILL_ALL_APPS + Constants.COLON + Constants.SPACE
329                        + Constants.APOSTROPHE + hostname + Constants.APOSTROPHE);
330                killPrinter.println(ScriptConstants.BIN_BASH_COMMENT);
331                killPrinter.println(ScriptConstants.CD + Constants.SPACE + getConfDirPath());
332                // insert path to kill script for all applications
333                for (Application app : applications) {
334                    // Constructing filename
335                    String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_LOCAL_KILL
336                            + app.getIdentification() + scriptExtension;
337                    // check if file exists
338                    killPrinter.println(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE + appScript + Constants.SPACE
339                            + ScriptConstants.LINUX_THEN + Constants.SPACE);
340                    killPrinter.println(ScriptConstants.MULTI_SPACE_6 + appScript);
341                    killPrinter.println(ScriptConstants.FI);
342                }
343
344                // kill the harvest database, if any, after the applications
345                killPrinter.print(callKillHarvestDatabase());
346                // kill the admin database, if any, after the applications
347                killPrinter.print(callKillArchiveDatabase());
348            } finally {
349                // close script
350                killPrinter.close();
351            }
352        } catch (IOException e) {
353            String msg = "Problems creating local kill all script. ";
354            log.error(msg, e);
355            throw new IOFailure(msg, e);
356        }
357    }
358
359    /**
360     * This function creates the script to start all applications on this machine. The scripts calls all the start
361     * script for each application. It also runs the script for starting any external database.
362     * <p>
363     * pseudo code: - echo Starting all applications at machine: mac - if [ -e ./start_app.sh ] - ./start_app.sh - fi -
364     * ...
365     * <p>
366     * where: mac = machine name. app = application name. ... = the same for other applications.
367     *
368     * @param directory The directory for this machine (use global variable?).
369     * @throws IOFailure If an error occurred during the creation of the local startall script.
370     */
371    @Override
372    protected void createOSLocalStartAllScript(File directory) throws IOFailure {
373        // create the start all script file
374        File startAllScript = new File(directory, Constants.SCRIPT_NAME_START_ALL + scriptExtension);
375        try {
376            // Initialise script
377            PrintWriter startPrinter = new PrintWriter(startAllScript, getTargetEncoding());
378            try {
379                startPrinter.println(ScriptConstants.BIN_BASH_COMMENT);
380                startPrinter.println(ScriptConstants.CD + Constants.SPACE + getConfDirPath());
381
382                // start the harvest database, if any, before the applications.
383                startPrinter.print(callStartHarvestDatabase());
384                // start the admin database, if any, before the applications.
385                startPrinter.print(callStartArchiveDatabase());
386
387                startPrinter.println(ScriptConstants.ECHO_START_ALL_APPS + Constants.COLON + Constants.SPACE
388                        + Constants.APOSTROPHE + hostname + Constants.APOSTROPHE);
389
390                // insert path to start script for each applications
391                for (Application app : applications) {
392                    // make name of file
393                    String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_LOCAL_START
394                            + app.getIdentification() + scriptExtension;
395                    // check if file exists
396                    startPrinter.println(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE + appScript + Constants.SPACE
397                            + ScriptConstants.LINUX_THEN + Constants.SPACE);
398                    startPrinter.println(ScriptConstants.MULTI_SPACE_6 + appScript);
399                    startPrinter.println(ScriptConstants.FI);
400                }
401            } finally {
402                // close script
403                startPrinter.close();
404            }
405        } catch (IOException e) {
406            String msg = "Problems creating local start all script. ";
407            log.trace(msg, e);
408            throw new IOFailure(msg, e);
409        }
410    }
411
412    /**
413     * Creates the kill scripts for all the applications.
414     * <p>
415     * The script starts by finding all running processes of the application. If it finds any processes, it kills them.
416     * <p>
417     * The kill_app.sh should have the following structure:
418     * <p>
419     * - echo Killing linux application. - #!/bin/bash - PIDS = $(ps -wwfe | grep fullapp | grep -v grep | grep
420     * path\settings_app.xml | awk "{print \\$2}") - if [ -n "$PIDS" ]; then - kill -9 $PIDS; - fi
421     * <p>
422     * Also, if a heritrix process is started, the following is added: - PIDS = $(ps -wwfe | grep heritrix | grep -v
423     * grep | grep path\settings_app.xml | awk "{print \\$2}") - if [ -n "$PIDS" ]; then - kill -9 $PIDS; - fi
424     * <p>
425     * where: path = the path to the ./conf directory. fullapp = the full application name with class path. app = the id
426     * of the application (name + instanceId). heritrix = the heritrix class path.
427     *
428     * @param directory The directory for this machine (use global variable?).
429     * @throws IOFailure If an error occured during the creation of the kill application script file.
430     */
431    @Override
432    protected void createApplicationKillScripts(File directory) throws IOFailure {
433        // go through all applications and create their kill script
434        for (Application app : applications) {
435            File appKillScript = new File(directory, Constants.SCRIPT_NAME_LOCAL_KILL + app.getIdentification()
436                    + scriptExtension);
437            try {
438                // make print writer for writing to file
439                PrintWriter appPrint = new PrintWriter(appKillScript, getTargetEncoding());
440                try {
441                    // echo Killing linux application.
442                    appPrint.println(ScriptConstants.ECHO_KILL_LINUX_APPLICATION + Constants.COLON + Constants.SPACE
443                            + app.getIdentification());
444                    // #!/bin/bash
445                    appPrint.println(ScriptConstants.BIN_BASH_COMMENT);
446
447                    // First try an ordinary kill, wait 2 seconds. Then test,
448                    // if process is still around. If it is make a hard kill
449                    // (-9)
450
451                    // PIDS = $(ps -wwfe | grep fullapp | grep -v grep | grep
452                    // path\settings_app.xml | awk "{print \\$2}")
453                    appPrint.println(ScriptConstants.getLinuxPIDS(app.getTotalName(), getConfDirPath(),
454                            app.getIdentification()));
455                    // if [ -n "$PIDS" ]; then
456                    appPrint.println(ScriptConstants.LINUX_IF_N_EXIST + Constants.SPACE + Constants.QUOTE_MARK
457                            + ScriptConstants.PIDS + Constants.QUOTE_MARK + Constants.SPACE
458                            + ScriptConstants.LINUX_N_THEN);
459
460                    appPrint.println(ScriptConstants.KILL_PIDS + Constants.SEMICOLON);
461                    // fi
462                    appPrint.println(ScriptConstants.FI);
463                    appPrint.println();
464                    appPrint.println(ScriptConstants.SLEEP_2);
465
466                    appPrint.println();
467                    // Set PIDS
468                    appPrint.println(ScriptConstants.getLinuxPIDS(app.getTotalName(), getConfDirPath(),
469                            app.getIdentification()));
470                    // IF
471                    appPrint.println(ScriptConstants.LINUX_IF_N_EXIST + Constants.SPACE + Constants.QUOTE_MARK
472                            + ScriptConstants.PIDS + Constants.QUOTE_MARK + Constants.SPACE
473                            + ScriptConstants.LINUX_N_THEN);
474
475                    // kill -9 $PIDS;
476                    appPrint.println(ScriptConstants.KILL_9_PIDS + Constants.SEMICOLON);
477                    // fi
478                    appPrint.println(ScriptConstants.FI);
479
480                    // If the application contains a heritrix instance,
481                    // then make script for killing the heritrix process.
482                    String[] heritrixJmxPort = app.getSettingsValues(Constants.SETTINGS_HARVEST_HERITRIX_JMX_PORT);
483                    if (heritrixJmxPort != null && heritrixJmxPort.length > 0) {
484                        // log if more than one jmx port defined for heritrix.
485                        if (heritrixJmxPort.length > 1) {
486                            log.trace(heritrixJmxPort.length + " number of jmx-ports for a heritrix " + "harvester.");
487                        }
488                        appPrint.println();
489                        // - PIDS = $(ps -wwfe | grep heritrix | grep -v grep
490                        // | grep path\settings_app.xml | awk "{print \\$2}")
491                        appPrint.println(ScriptConstants.getLinuxPIDS(HERITRIX_1_CLASSNAME, getConfDirPath(),
492                                app.getIdentification()));
493                        // - if [ -n "$PIDS" ]; then
494                        appPrint.println(ScriptConstants.LINUX_IF_N_EXIST + Constants.SPACE + Constants.QUOTE_MARK
495                                + ScriptConstants.PIDS + Constants.QUOTE_MARK + Constants.SPACE
496                                + ScriptConstants.LINUX_N_THEN);
497                        // first make a ordinary kill, wait 2 seconds, then make a
498                        // hard kill -9
499                        appPrint.println(ScriptConstants.KILL_PIDS + Constants.SEMICOLON);
500                        // - fi
501                        appPrint.println(ScriptConstants.FI);
502                        appPrint.println();
503                        // wait 2 seconds
504                        appPrint.println(ScriptConstants.SLEEP_2);
505                        appPrint.println();
506                        // See if Process is still around
507                        appPrint.println(ScriptConstants.getLinuxPIDS(HERITRIX_1_CLASSNAME, getConfDirPath(),
508                                app.getIdentification()));
509                        // if still around
510                        appPrint.println(ScriptConstants.LINUX_IF_N_EXIST + Constants.SPACE + Constants.QUOTE_MARK
511                                + ScriptConstants.PIDS + Constants.QUOTE_MARK + Constants.SPACE
512                                + ScriptConstants.LINUX_N_THEN);
513                        // - kill -9 $PIDS;
514                        appPrint.println(ScriptConstants.KILL_9_PIDS + Constants.SEMICOLON);
515                        // - fi
516                        appPrint.println(ScriptConstants.FI);
517                    }
518                } finally {
519                    // close file
520                    appPrint.close();
521                }
522            } catch (IOException e) {
523                String msg = "Problems creating application kill script: ";
524                log.error(msg, e);
525                throw new IOFailure(msg, e);
526            }
527        }
528    }
529
530    /**
531     * Creates the start scripts for all the applications.
532     * <p>
533     * The application should only be started, if it is not running already. The script starts by finding all running
534     * processes of the application. If any processes are found, a new application should not be started. Otherwise
535     * start the application.
536     * <p>
537     * The start_app.sh should have the following structure:
538     * <p>
539     * - echo Starting linux application: app - cd path - #!/bin/bash - PIDS = $(ps -wwfe | grep fullapp | grep -v grep
540     * | grep path\settings_app.xml | awk "{print \\$2}") - if [ -n "$PIDS" ]; then - echo Application already running.
541     * - else - export CLASSPATH = cp:$CLASSPATH; - JAVA - fi
542     * <p>
543     * where: path = the path to the install directory. fullapp = the full name application with java path. app = the
544     * name of the application. cp = the classpaths for the application. JAVA = the command to run the java application.
545     *
546     * @param directory The directory for this machine (use global variable?).
547     * @throws IOFailure If an error occurred during the creation of the start application script file.
548     */
549    @Override
550    protected void createApplicationStartScripts(File directory) throws IOFailure {
551        // go through all applications and create their start script
552        for (Application app : applications) {
553            if (app.getTotalName().contains("GUI")) {
554                 createHarvestDatabaseUpdateScript(directory, true);
555            }
556            File appStartScript = new File(directory, Constants.SCRIPT_NAME_LOCAL_START + app.getIdentification()
557                    + scriptExtension);
558            try {
559                // make print writer for writing to file
560                PrintWriter appPrint = new PrintWriter(appStartScript, getTargetEncoding());
561                try {
562                    // #!/bin/bash
563                    appPrint.println(ScriptConstants.ECHO_START_LINUX_APP + Constants.COLON + Constants.SPACE
564                            + app.getIdentification());
565                    // cd path
566                    appPrint.println(ScriptConstants.CD + Constants.SPACE + app.installPathLinux());
567                    // PIDS = $(ps -wwfe | grep fullapp | grep -v grep | grep
568                    // path\settings_app.xml | awk "{print \\$2}")
569                    appPrint.println(ScriptConstants.getLinuxPIDS(app.getTotalName(), getConfDirPath(),
570                            app.getIdentification()));
571                    // if [ -n "$PIDS" ]; then
572                    appPrint.println(ScriptConstants.LINUX_IF_N_EXIST + Constants.SPACE + Constants.QUOTE_MARK
573                            + ScriptConstants.PIDS + Constants.QUOTE_MARK + Constants.SPACE
574                            + ScriptConstants.LINUX_N_THEN);
575                    // echo Application already running.
576                    appPrint.println(ScriptConstants.ECHO_APP_ALREADY_RUNNING);
577                    // else
578                    appPrint.println(ScriptConstants.ELSE);
579                    // export CLASSPATH = cp;
580                    appPrint.println(ScriptConstants.MULTI_SPACE_4 + ScriptConstants.EXPORT_CLASSPATH
581                            + osGetClassPath(app) + ScriptConstants.VALUE_OF_CLASSPATH + Constants.SEMICOLON);
582                    // JAVA
583                    String securityManagement = "";
584                    if (app.getTotalName().contains(ScriptConstants.BITARCHIVE_APPLICATION_NAME)) {
585                        securityManagement = Constants.SPACE + Constants.DASH + ScriptConstants.OPTION_SECURITY_MANAGER
586                                + Constants.SPACE + Constants.DASH + ScriptConstants.OPTION_SECURITY_POLICY
587                                + getConfDirPath() + Constants.SECURITY_POLICY_FILE_NAME;
588                    }
589                    //}
590                    appPrint.println(ScriptConstants.MULTI_SPACE_4
591                            + ScriptConstants.JAVA
592                            + Constants.SPACE
593                            + app.getMachineParameters().writeJavaOptions()
594                            + Constants.SPACE
595                            + Constants.DASH
596                            + ScriptConstants.OPTION_SETTINGS
597                            + getConfDirPath()
598                            + Constants.PREFIX_SETTINGS
599                            + app.getIdentification()
600                            + Constants.EXTENSION_XML_FILES
601
602                            // TODO check to see if inheritedSlf4jConfigFile is not null
603                            + Constants.SPACE + Constants.DASH + ScriptConstants.OPTION_LOGBACK_CONFIG
604                            + getConfDirPath() + Constants.LOGBACK_PREFIX + app.getIdentification()
605                            + Constants.EXTENSION_XML_FILES
606
607                            + securityManagement
608                            + Constants.SPACE + app.getTotalName() + Constants.SPACE + ScriptConstants.LINUX_DEV_NULL
609                            + Constants.SPACE + Constants.SCRIPT_NAME_LOCAL_START + app.getIdentification()
610                            + Constants.EXTENSION_LOG_FILES + Constants.SPACE
611                            + ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
612                    // fi
613                    appPrint.println(ScriptConstants.FI);
614                } finally {
615                    // close file
616                    appPrint.close();
617                }
618            } catch (IOException e) {
619                String msg = "Problems creating application start script. ";
620                log.trace(msg, e);
621                throw new IOFailure(msg, e);
622            }
623        }
624    }
625
626    @Override
627    protected String osGetClassPath(Application app) {
628        StringBuilder res = new StringBuilder();
629        // get all the classpaths
630        for (Element cp : app.getMachineParameters().getClassPaths()) {
631            res.append(getInstallDirPath() + Constants.SLASH + cp.getText().trim() + Constants.COLON);
632        }
633        return res.toString();
634    }
635
636    @Override
637    protected String osInstallDatabase() {
638        StringBuilder res = new StringBuilder();
639
640        String databaseDir = machineParameters.getHarvestDatabaseDirValue();
641        // Do not install if no proper database directory.
642        if (databaseDir == null || databaseDir.isEmpty()) {
643            return Constants.EMPTY;
644        }
645
646        // copy to final destination if database argument.
647        if (databaseFile != null) {
648            // echo Copying database
649            res.append(ScriptConstants.ECHO_COPYING_DATABASE);
650            res.append(Constants.NEWLINE);
651            // scp database.jar user@machine:dbDir/db
652            res.append(ScriptConstants.SCP + Constants.SPACE);
653            res.append(databaseFile.getPath());
654            res.append(Constants.SPACE);
655            res.append(machineUserLogin());
656            res.append(Constants.COLON);
657            res.append(getInstallDirPath());
658            res.append(Constants.SLASH);
659            res.append(Constants.HARVEST_DATABASE_BASE_PATH);
660            res.append(Constants.NEWLINE);
661        }
662        // unzip database.
663        res.append(ScriptConstants.ECHO_UNZIPPING_DATABASE);
664        res.append(Constants.NEWLINE);
665        // ssh user@machine "
666        // cd dir; if [ -d databaseDir ]; then echo ;
667        // else mkdir databaseDir; fi; if [ $(ls -A databaseDir) ];
668        // then echo ERROR MESSAGE: DIR NOT EMPTY;
669        // else unzip -q -o dbDir/db -d databaseDir/.; fi; exit;
670        // "
671        res.append(ScriptConstants.SSH + Constants.SPACE);
672        res.append(machineUserLogin());
673        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.CD + Constants.SPACE);
674        res.append(getInstallDirPath());
675        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.LINUX_IF_DIR_EXIST + Constants.SPACE);
676        res.append(databaseDir);
677        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.ECHO
678                + Constants.SPACE);
679        res.append(ScriptConstants.DATABASE_ERROR_PROMPT_DIR_NOT_EMPTY);
680        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.ELSE + Constants.SPACE
681                + ScriptConstants.LINUX_UNZIP_COMMAND + Constants.SPACE);
682        res.append(Constants.HARVEST_DATABASE_BASE_PATH);
683        res.append(Constants.SPACE + ScriptConstants.SCRIPT_DIR + Constants.SPACE);
684        res.append(databaseDir);
685        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.FI + Constants.SEMICOLON + Constants.SPACE
686                + ScriptConstants.EXIT + Constants.SEMICOLON + Constants.SPACE + Constants.QUOTE_MARK);
687        res.append(Constants.NEWLINE);
688
689        return res.toString();
690    }
691
692    @Override
693    protected String osInstallExternalJarFiles() {
694        if (jarFolder == null) {
695            return Constants.EMPTY;
696        }
697
698        StringBuilder res = new StringBuilder();
699
700        // Comment about copying files.
701        res.append(ScriptConstants.ECHO_INSTALLING_EXTERNAL_JAR_FILES);
702        res.append(Constants.NEWLINE);
703        // if [ -d folder ]; then scp folder machine:installdir/external; fi;
704        res.append(ScriptConstants.LINUX_IF_DIR_EXIST + Constants.SPACE);
705        res.append(jarFolder.getPath());
706        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.SCP
707                + Constants.SPACE + ScriptConstants.DASH_R + Constants.SPACE);
708        res.append(jarFolder.getPath());
709        res.append(Constants.SPACE);
710        res.append(machineUserLogin());
711        res.append(Constants.COLON);
712        res.append(getInstallDirPath());
713        res.append(Constants.SLASH + Constants.EXTERNAL_JAR_DIRECTORY + Constants.SEMICOLON + Constants.SPACE
714                + ScriptConstants.FI + Constants.SEMICOLON);
715        res.append(Constants.NEWLINE);
716
717        return res.toString();
718    }
719
720    @Override
721    protected String osInstallArchiveDatabase() {
722        String adminDatabaseDir = machineParameters.getArchiveDatabaseDirValue();
723        // Do not install if no proper archive database directory.
724        if (adminDatabaseDir == null || adminDatabaseDir.isEmpty()) {
725            return Constants.EMPTY;
726        }
727
728        // Initialise the StringBuilder containing the resulting script.
729        StringBuilder res = new StringBuilder();
730
731        // copy to final destination if database argument.
732        if (arcDatabaseFile != null) {
733            // echo Copying database
734            res.append(ScriptConstants.ECHO_COPYING_ARCHIVE_DATABASE);
735            res.append(Constants.NEWLINE);
736            // scp database.jar user@machine:dbDir/bpdb
737            res.append(ScriptConstants.SCP + Constants.SPACE);
738            res.append(arcDatabaseFile.getPath());
739            res.append(Constants.SPACE);
740            res.append(machineUserLogin());
741            res.append(Constants.COLON);
742            res.append(getInstallDirPath());
743            res.append(Constants.SLASH);
744            // Now the two databases are in different directories
745            res.append(Constants.ARCHIVE_DATABASE_BASE_PATH);
746            res.append(Constants.NEWLINE);
747        }
748        // unzip database.
749        res.append(ScriptConstants.ECHO_UNZIPPING_ARCHIVE_DATABASE);
750        res.append(Constants.NEWLINE);
751        // ssh user@machine "
752        // cd dir; if [ -d bpDatabaseDir ]; then echo ;
753        // else mkdir bpDatabaseDir; fi; if [ $(ls -A bpDatabaseDir) ];
754        // then echo ERROR MESSAGE: DIR NOT EMPTY;
755        // else unzip -q -o dbDir/bpdb -d databaseDir/.; fi; exit;
756        // "
757        res.append(ScriptConstants.SSH + Constants.SPACE);
758        res.append(machineUserLogin());
759        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.CD + Constants.SPACE);
760        res.append(getInstallDirPath());
761        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.LINUX_IF_DIR_EXIST + Constants.SPACE);
762        res.append(adminDatabaseDir);
763        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.ECHO
764                + Constants.SPACE);
765        res.append(ScriptConstants.DATABASE_ERROR_PROMPT_DIR_NOT_EMPTY);
766        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.ELSE + Constants.SPACE
767                + ScriptConstants.LINUX_UNZIP_COMMAND + Constants.SPACE);
768        res.append(Constants.ARCHIVE_DATABASE_BASE_PATH);
769        res.append(Constants.SPACE + ScriptConstants.SCRIPT_DIR + Constants.SPACE);
770        res.append(adminDatabaseDir);
771        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.FI + Constants.SEMICOLON + Constants.SPACE
772                + ScriptConstants.EXIT + Constants.SEMICOLON + Constants.SPACE + Constants.QUOTE_MARK);
773        res.append(Constants.NEWLINE);
774
775        return res.toString();
776    }
777
778    /**
779     * Creates the specified directories in the deploy-configuration file.
780     * <p>
781     * Structure - ssh login cd path; DIRS; CLEANDIR; exit;
782     * <p>
783     * where: login = username@machine. path = path to install directory. DIRS = the way to create directories. CLEANDIR
784     * = the command to clean the tempDir (if chosen as optional)
785     * <p>
786     * The install creation of DIR has the following structure for directory dir: if [ ! -d dir ]; then mkdir dir; fi;
787     *
788     * @return The script for creating the directories.
789     */
790    @Override
791    protected String osInstallScriptCreateDir() {
792        StringBuilder res = new StringBuilder();
793        res.append(ScriptConstants.ECHO_CREATING_DIRECTORIES);
794        res.append(Constants.NEWLINE);
795        res.append(ScriptConstants.SSH + Constants.SPACE);
796        res.append(machineUserLogin());
797        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.CD + Constants.SPACE);
798        res.append(getInstallDirPath());
799        res.append(Constants.SEMICOLON + Constants.SPACE);
800
801        // go through all directories.
802        String dir;
803
804        // get archive.bitpresevation.baseDir directory.
805        dir = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_BP_BASEDIR_LEAF);
806        if (dir != null && !dir.isEmpty() && !dir.equalsIgnoreCase(Constants.DOT)) {
807            res.append(createPathToDir(dir));
808            res.append(scriptCreateDir(dir, false));
809        }
810
811        // get archive.arcrepository.baseDir directory.
812        dir = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_ARC_BASEDIR_LEAF);
813        if (dir != null && !dir.isEmpty() && !dir.equalsIgnoreCase(Constants.DOT)) {
814            res.append(scriptCreateDir(dir, false));
815        }
816
817        // get tempDir directory.
818        dir = settings.getLeafValue(Constants.SETTINGS_TEMPDIR_LEAF);
819        if (dir != null && !dir.isEmpty() && !dir.equalsIgnoreCase(Constants.DOT)) {
820            res.append(createPathToDir(dir));
821            res.append(scriptCreateDir(dir, resetTempDir));
822        }
823
824        // get the application specific directories.
825        res.append(getAppDirectories());
826
827        res.append(ScriptConstants.EXIT + Constants.SEMICOLON + Constants.SPACE + Constants.QUOTE_MARK
828                + Constants.NEWLINE);
829
830        return res.toString();
831    }
832
833    @Override
834    protected String scriptCreateDir(String dir, boolean clean) {
835        StringBuilder res = new StringBuilder();
836        res.append(ScriptConstants.LINUX_IF_NOT_DIR_EXIST + Constants.SPACE);
837        res.append(dir);
838        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.MKDIR
839                + Constants.SPACE);
840        res.append(dir);
841        if (clean) {
842            res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.ELSE_REMOVE + Constants.SPACE);
843            res.append(dir);
844            res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.MKDIR + Constants.SPACE);
845            res.append(dir);
846        }
847        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.FI + Constants.SEMICOLON + Constants.SPACE);
848
849        return res.toString();
850    }
851
852    /**
853     * Function for creating the directories along the path until the end directory. Does not create the end directory.
854     *
855     * @param dir The path to the directory.
856     * @return The script for creating the directory.
857     */
858    protected String createPathToDir(String dir) {
859        StringBuilder res = new StringBuilder();
860
861        String[] pathDirs = dir.split(Constants.REGEX_SLASH_CHARACTER);
862        StringBuilder path = new StringBuilder();
863
864        // only make directories along path to last directory,
865        // don't create end directory.
866        for (int i = 0; i < pathDirs.length - 1; i++) {
867            // don't make directory of empty path.
868            if (!pathDirs[i].isEmpty()) {
869                path.append(pathDirs[i]);
870                res.append(scriptCreateDir(path.toString(), false));
871            }
872            path.append(Constants.SLASH);
873        }
874
875        return res.toString();
876    }
877
878    @Override
879    protected String getAppDirectories() {
880        StringBuilder res = new StringBuilder();
881        String[] dirs;
882
883        for (Application app : applications) {
884            // get archive.fileDir directories.
885            dirs = app.getSettingsValues(Constants.SETTINGS_BITARCHIVE_BASEFILEDIR_LEAF);
886            if (dirs != null && dirs.length > 0) {
887                for (String dir : dirs) {
888                    res.append(createPathToDir(dir));
889                    res.append(scriptCreateDir(dir, false));
890                    for (String subdir : Constants.BASEFILEDIR_SUBDIRECTORIES) {
891                        res.append(scriptCreateDir(dir + Constants.SLASH + subdir, false));
892                    }
893                }
894            }
895
896            // get harvester.harvesting.serverDir directories.
897            dirs = app.getSettingsValues(Constants.SETTINGS_HARVEST_SERVERDIR_LEAF);
898            if (dirs != null && dirs.length > 0) {
899                for (String dir : dirs) {
900                    res.append(createPathToDir(dir));
901                    res.append(scriptCreateDir(dir, false));
902                }
903            }
904
905            // get the viewerproxy.baseDir directories.
906            dirs = app.getSettingsValues(Constants.SETTINGS_VIEWERPROXY_BASEDIR_LEAF);
907            if (dirs != null && dirs.length > 0) {
908                for (String dir : dirs) {
909                    res.append(createPathToDir(dir));
910                    res.append(scriptCreateDir(dir, false));
911                }
912            }
913
914            // get the common.tempDir directories. But only those,
915            // which are not the same as the machine common.tempDir.
916            dirs = app.getSettingsValues(Constants.SETTINGS_TEMPDIR_LEAF);
917            if (dirs != null && dirs.length > 0) {
918                String machineDir = settings.getLeafValue(Constants.SETTINGS_TEMPDIR_LEAF);
919                for (String dir : dirs) {
920                    // Don't make machine temp dir twice.
921                    if (!dir.equals(machineDir)) {
922                        res.append(createPathToDir(dir));
923                        res.append(scriptCreateDir(dir, resetTempDir));
924                    }
925                }
926            }
927        }
928
929        return res.toString();
930    }
931
932    /**
933     * Dummy function on linux machine. This is only used for windows machines!
934     *
935     * @param dir The directory to put the file.
936     */
937    @Override
938    protected void createInstallDirScript(File dir) {
939        // Do nothing. Dummy function on linux machine.
940    }
941
942    @Override
943    protected String changeFileDirPathForSecurity(String path) {
944        path += Constants.SLASH + Constants.SECURITY_FILE_DIR_TAG + Constants.SLASH;
945        return path.replace(Constants.SLASH, ScriptConstants.SECURITY_DIR_SEPARATOR);
946    }
947
948    @Override
949    protected String getJMXremoteFilesCommand() {
950        String accessFilePath;
951        String passwordFilePath;
952        String[] options;
953
954        // retrieve the access file path.
955        options = settings.getLeafValues(Constants.SETTINGS_COMMON_JMX_ACCESSFILE);
956
957        // extract the path, if any. Else set default.
958        if (options.length == 0) {
959            accessFilePath = Constants.JMX_ACCESS_FILE_PATH_DEFAULT;
960        } else {
961            accessFilePath = options[0];
962            // warn if more than one access file is defined.
963            if (options.length > 1) {
964                log.debug(Constants.MSG_WARN_TOO_MANY_JMXREMOTE_FILE_PATHS);
965            }
966        }
967
968        // retrieve the password file path.
969        options = settings.getLeafValues(Constants.SETTINGS_COMMON_JMX_PASSWORDFILE);
970
971        // extract the path, if any. Else set default.
972        if (options.length == 0) {
973            passwordFilePath = Constants.JMX_PASSWORD_FILE_PATH_DEFAULT;
974        } else {
975            passwordFilePath = options[0];
976            // warn if more than one access file is defined.
977            if (options.length > 1) {
978                log.debug(Constants.MSG_WARN_TOO_MANY_JMXREMOTE_FILE_PATHS);
979            }
980        }
981
982        // initialise the resulting command string.
983        StringBuilder res = new StringBuilder();
984
985        // echo make password files readonly
986        res.append(ScriptConstants.ECHO_MAKE_PASSWORD_FILES);
987        res.append(Constants.NEWLINE);
988
989        // IF NOT DEFAULT PATHS, THEN MAKE SCRIPT TO MOVE THE FILES.
990        if (!accessFilePath.equals(Constants.JMX_ACCESS_FILE_PATH_DEFAULT)) {
991            // ssh dev@kb-test-adm-001.kb.dk "mv -f
992            // installpath/conf/jmxremote.access installpath/accessFilePath"
993            res.append(ScriptConstants.SSH + Constants.SPACE);
994            res.append(machineUserLogin());
995            res.append(Constants.SPACE + Constants.QUOTE_MARK);
996            res.append(ScriptConstants.LINUX_FORCE_MOVE);
997            res.append(Constants.SPACE);
998            res.append(getInstallDirPath());
999            res.append(Constants.SLASH);
1000            res.append(Constants.JMX_ACCESS_FILE_PATH_DEFAULT);
1001            res.append(Constants.SPACE);
1002            res.append(getInstallDirPath());
1003            res.append(Constants.SLASH);
1004            res.append(accessFilePath);
1005            res.append(Constants.QUOTE_MARK);
1006            res.append(Constants.NEWLINE);
1007        }
1008
1009        if (!passwordFilePath.equals(Constants.JMX_PASSWORD_FILE_PATH_DEFAULT)) {
1010            // ssh dev@kb-test-adm-001.kb.dk "mv -f
1011            // installpath/conf/jmxremote.access installpath/accessFilePath"
1012            res.append(ScriptConstants.SSH + Constants.SPACE);
1013            res.append(machineUserLogin());
1014            res.append(Constants.SPACE + Constants.QUOTE_MARK);
1015            res.append(ScriptConstants.LINUX_FORCE_MOVE);
1016            res.append(Constants.SPACE);
1017            res.append(getInstallDirPath());
1018            res.append(Constants.SLASH);
1019            res.append(Constants.JMX_PASSWORD_FILE_PATH_DEFAULT);
1020            res.append(Constants.SPACE);
1021            res.append(getInstallDirPath());
1022            res.append(Constants.SLASH);
1023            res.append(passwordFilePath);
1024            res.append(Constants.QUOTE_MARK);
1025            res.append(Constants.NEWLINE);
1026        }
1027
1028        // Allow only user to be able to only read jmxremote.password
1029        // (a=-rwx,u=+r) = 400.
1030        // ssh dev@kb-test-adm-001.kb.dk "chmod 400
1031        // /home/dev/TEST/conf/jmxremote.password"
1032        res.append(ScriptConstants.SSH + Constants.SPACE);
1033        res.append(machineUserLogin());
1034        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.LINUX_USER_400 + Constants.SPACE);
1035        res.append(getInstallDirPath());
1036        res.append(Constants.SLASH);
1037        res.append(passwordFilePath);
1038        res.append(Constants.QUOTE_MARK);
1039        res.append(Constants.NEWLINE);
1040        // ssh dev@kb-test-adm-001.kb.dk "chmod 400
1041        // /home/dev/TEST/conf/jmxremote.access"
1042        res.append(ScriptConstants.SSH + Constants.SPACE);
1043        res.append(machineUserLogin());
1044        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.LINUX_USER_400 + Constants.SPACE);
1045        res.append(getInstallDirPath());
1046        res.append(Constants.SLASH);
1047        res.append(accessFilePath);
1048        res.append(Constants.QUOTE_MARK);
1049        res.append(Constants.NEWLINE);
1050
1051        return res.toString();
1052    }
1053
1054    /**
1055     * Creates script for restarting all the applications on a machine. This script should start by killing all the
1056     * existing processes, and then starting them again.
1057     * <p>
1058     * First the killall scripts is called, then wait for 5 seconds for the applications to be fully terminated, and
1059     * finally the startall script is called.
1060     *
1061     * @param dir The directory where the script file will be placed.
1062     * @throws IOFailure If the restart script cannot be created.
1063     */
1064    @Override
1065    protected void createRestartScript(File dir) throws IOFailure {
1066        try {
1067            // initialise the script file.
1068            File restartScript = new File(dir, Constants.SCRIPT_NAME_RESTART + scriptExtension);
1069
1070            // make print writer for writing to file
1071            PrintWriter restartPrint = new PrintWriter(restartScript, getTargetEncoding());
1072            try {
1073                // init, go to directory
1074                restartPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1075                restartPrint.println(ScriptConstants.CD + Constants.SPACE + getConfDirPath());
1076
1077                // call killall script.
1078                restartPrint.print(Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_KILL_ALL + scriptExtension);
1079                restartPrint.print(Constants.NEWLINE);
1080
1081                // call wait script.
1082                restartPrint.print(ScriptConstants.SLEEP);
1083                restartPrint.print(Constants.SPACE);
1084                restartPrint.print(Constants.WAIT_TIME_DURING_RESTART);
1085                restartPrint.print(Constants.NEWLINE);
1086
1087                // call startall script.
1088                restartPrint.print(Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_START_ALL + scriptExtension);
1089                restartPrint.print(Constants.NEWLINE);
1090            } finally {
1091                // close file
1092                restartPrint.close();
1093            }
1094        } catch (IOException e) {
1095            // Log the error and throw an IOFailure.
1096            log.trace(Constants.MSG_ERROR_RESTART_FILE, e);
1097            throw new IOFailure(Constants.MSG_ERROR_RESTART_FILE, e);
1098        }
1099    }
1100
1101    /**
1102     * Creates a script for starting the archive database on a given machine. This is only created if the
1103     * &lt;globalArchiveDatabaseDir&gt; parameter is defined on the machine level.
1104     * <p>
1105     * <br/>
1106     * &gt; #!/bin/bash <br/>
1107     * &gt; cd InstallDir <br/>
1108     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl start < /dev/null >
1109     * start_external_database.log 2>&1 &
1110     *
1111     * @param dir The directory where the script will be placed.
1112     * @throws IOFailure If the script cannot be written.
1113     */
1114    @Override
1115    protected void createArchiveDatabaseStartScript(File dir) throws IOFailure {
1116
1117        // Ignore if no archive database directory has been defined.
1118        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1119        if (dbDir.isEmpty()) {
1120            return;
1121        }
1122
1123        try {
1124            // initialise the script file.
1125            File startArcDBScript = new File(dir, Constants.SCRIPT_NAME_ADMIN_DB_START + scriptExtension);
1126
1127            // retrieve the port
1128            String port = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_DATABASE_PORT);
1129
1130            // make print writer for writing to file
1131            PrintWriter startDBPrint = new PrintWriter(startArcDBScript, getTargetEncoding());
1132            try {
1133                // - #!/bin/bash
1134                startDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1135                // - cd InstallDir
1136                startDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1137                startDBPrint.println(getInstallDirPath());
1138                // - java -Dderby.system.home=$INSTALLDIR/archivedatabasedir
1139                // -cp 'DB-CLASSPATH'
1140                // org.apache.derby.drda.NetworkServerControl start
1141                // < /dev/null > start_external_database.log 2>&1 &
1142                startDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1143                // FIXME: Incomplete implementation of NAS-2030
1144                // startDBPrint.print("-Dderby.system.home="
1145                // + getInstallDirPath() + Constants.SLASH
1146                // + dbDir
1147                // + Constants.SPACE);
1148
1149                startDBPrint.print(machineParameters.writeJavaOptions());
1150                startDBPrint.print(Constants.SPACE);
1151                startDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1152                startDBPrint.print(Constants.SPACE + getDbClasspaths());
1153                startDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1154                // insert the PORT if any specified.
1155                if (port != null && !port.isEmpty()) {
1156                    startDBPrint.print(Constants.SPACE);
1157                    startDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1158                    startDBPrint.print(Constants.SPACE);
1159                    startDBPrint.print(port);
1160                }
1161                startDBPrint.print(Constants.SPACE);
1162                startDBPrint.print(ScriptConstants.DERBY_COMMAND_START);
1163                startDBPrint.print(Constants.SPACE);
1164                startDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1165                startDBPrint.print(Constants.SPACE);
1166                startDBPrint.print(Constants.SCRIPT_NAME_ADMIN_DB_START);
1167                startDBPrint.print(Constants.EXTENSION_LOG_FILES);
1168                startDBPrint.print(Constants.SPACE);
1169                startDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1170            } finally {
1171                // close file
1172                startDBPrint.close();
1173            }
1174        } catch (IOException e) {
1175            // Log the error and throw an IOFailure.
1176            log.trace(Constants.MSG_ERROR_DB_START_FILE, e);
1177            throw new IOFailure(Constants.MSG_ERROR_DB_START_FILE, e);
1178        }
1179    }
1180
1181    /**
1182     * Method for generating the command for running the external_admin_database_start script. This should be called
1183     * before the application on the machines have been started.
1184     * <p>
1185     * <br/>
1186     * &gt; echo Starting external database <br/>
1187     * &gt; if [ -e ./start_external_admin_database.sh ]; then <br/>
1188     * &gt; ./start_external_admin_database.sh & <br/>
1189     * &gt; sleep 5 <br/>
1190     * &gt; fi
1191     *
1192     * @return The command for running external_admin_database_start script.
1193     */
1194    protected String callStartArchiveDatabase() {
1195        // Ignore if no archive database directory has been defined.
1196        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1197        if (dbDir.isEmpty()) {
1198            return "";
1199        }
1200
1201        // Constructing filename
1202        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_ADMIN_DB_START + scriptExtension;
1203
1204        StringBuilder res = new StringBuilder();
1205        // echo Starting external database
1206        res.append(ScriptConstants.ECHO_START_EXTERNAL_ADMIN_DATABASE);
1207        res.append(Constants.NEWLINE);
1208        // if [ -e ./start_external_database.sh ]; then
1209        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1210        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1211        res.append(Constants.NEWLINE);
1212        // ./start_external_database.sh
1213        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1214        res.append(ScriptConstants.LINUX_RUN_BACKGROUND + Constants.NEWLINE);
1215        // sleep 5
1216        res.append(ScriptConstants.MULTI_SPACE_6 + ScriptConstants.SLEEP_5);
1217        res.append(Constants.NEWLINE);
1218        // fi
1219        res.append(ScriptConstants.FI + Constants.NEWLINE);
1220
1221        return res.toString();
1222    }
1223
1224    /**
1225     * Creates a script for killing the archive database on a given machine. This is only created if the
1226     * &lt;globalArchiveDatabaseDir&gt; parameter is defined on the machine level.
1227     * <p>
1228     * The output is appended to the log, thus the '>>' instead of the standard '>' when redirecting the output.
1229     * <p>
1230     * <br/>
1231     * &gt; #!/bin/bash <br/>
1232     * &gt; cd InstallDir <br/>
1233     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl shutdown < /dev/null >>
1234     * start_external_database.log 2>&1 &
1235     * <p>
1236     * <br/>
1237     * where 'PORT' is in the setting: settings.archive.admin.database.port
1238     *
1239     * @param dir The directory where the script will be placed.
1240     * @throws IOFailure If the script cannot be created.
1241     */
1242    @Override
1243    protected void createArchiveDatabaseKillScript(File dir) throws IOFailure {
1244        // Ignore if no archive database directory has been defined.
1245        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1246        if (dbDir.isEmpty()) {
1247            return;
1248        }
1249
1250        try {
1251            // initialise the script file.
1252            File killArcDBScript = new File(dir, Constants.SCRIPT_NAME_ADMIN_DB_KILL + scriptExtension);
1253
1254            // retrieve the port for the database.
1255            String port = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_DATABASE_PORT);
1256
1257            // make print writer for writing to file
1258            PrintWriter killDBPrint = new PrintWriter(killArcDBScript, getTargetEncoding());
1259            try {
1260                // - #!/bin/bash
1261                killDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1262
1263                // - cd InstallDir
1264                killDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1265                killDBPrint.println(getInstallDirPath());
1266                // - java -cp 'DB-CLASSPATH'
1267                // org.apache.derby.drda.NetworkServerControl shutdown
1268                // < /dev/null >> start_external_database.log 2>&1 &
1269                killDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1270                killDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1271                killDBPrint.print(Constants.SPACE + getDbClasspaths());
1272                killDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1273                // insert the PORT if any specified.
1274                if (port != null && !port.isEmpty()) {
1275                    killDBPrint.print(Constants.SPACE);
1276                    killDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1277                    killDBPrint.print(Constants.SPACE);
1278                    killDBPrint.print(port);
1279                }
1280                killDBPrint.print(Constants.SPACE);
1281                killDBPrint.print(ScriptConstants.DERBY_COMMAND_KILL);
1282                killDBPrint.print(Constants.SPACE);
1283                killDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1284                killDBPrint.print(Constants.GREATER_THAN);
1285                killDBPrint.print(Constants.SPACE);
1286                killDBPrint.print(Constants.SCRIPT_NAME_ADMIN_DB_START);
1287                killDBPrint.print(Constants.EXTENSION_LOG_FILES);
1288                killDBPrint.print(Constants.SPACE);
1289                killDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1290            } finally {
1291                // close file
1292                killDBPrint.close();
1293            }
1294        } catch (IOException e) {
1295            // Log the error and throw an IOFailure.
1296            log.trace(Constants.MSG_ERROR_DB_KILL_FILE, e);
1297            throw new IOFailure(Constants.MSG_ERROR_DB_KILL_FILE, e);
1298        }
1299    }
1300
1301    /**
1302     * Method for generating the command for running the external_database_kill script. This should be called when the
1303     * application on the machines have been killed.
1304     * <p>
1305     * <br/>
1306     * &gt; echo Killing external database <br/>
1307     * &gt; if [ -e ./kill_external_database.sh ]; then <br/>
1308     * &gt; ./kill_external_database.sh <br/>
1309     * &gt; fi
1310     *
1311     * @return The command for running external_database_kill script.
1312     */
1313    protected String callKillArchiveDatabase() {
1314        // Ignore if no archive database directory has been defined.
1315        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1316        if (dbDir.isEmpty()) {
1317            return "";
1318        }
1319
1320        // Constructing filename
1321        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_ADMIN_DB_KILL + scriptExtension;
1322
1323        StringBuilder res = new StringBuilder();
1324        // echo Killing external database
1325        res.append(ScriptConstants.ECHO_KILL_EXTERNAL_ADMIN_DATABASE);
1326        res.append(Constants.NEWLINE);
1327        // if [ -e ./kill_external_database.sh ]; then
1328        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1329        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1330        res.append(Constants.NEWLINE);
1331        // ./kill_external_database.sh
1332        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1333        res.append(Constants.NEWLINE);
1334        // fi
1335        res.append(ScriptConstants.FI + Constants.NEWLINE);
1336
1337        return res.toString();
1338    }
1339
1340    /**
1341     * Creates a script for starting the harvest database on a given machine. This is only created if the
1342     * &lt;deployHarvestDatabaseDir&gt; parameter is defined on the machine level.
1343     * <p>
1344     * <br/>
1345     * &gt; #!/bin/bash <br/>
1346     * &gt; cd InstallDir <br/>
1347     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl start < /dev/null >
1348     * start_external_harvest_database.log 2>&1 &
1349     *
1350     * @param dir The directory where the script will be placed.
1351     * @throws IOFailure If the script cannot be written.
1352     */
1353    @Override
1354    protected void createHarvestDatabaseStartScript(File dir) throws IOFailure {
1355        // Ignore if no harvest database directory has been defined.
1356        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1357        if (dbDir.isEmpty()) {
1358            return;
1359        }
1360
1361        try {
1362            // initialise the script file.
1363            File startHarvestDBScript = new File(dir, Constants.SCRIPT_NAME_HARVEST_DB_START + scriptExtension);
1364
1365            // retrieve the port
1366            String port = settings.getLeafValue(Constants.SETTINGS_HARVEST_DATABASE_PORT);
1367
1368            // make print writer for writing to file
1369            PrintWriter startDBPrint = new PrintWriter(startHarvestDBScript, getTargetEncoding());
1370            try {
1371                // - #!/bin/bash
1372                startDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1373                // - cd InstallDir
1374                startDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1375                startDBPrint.println(getInstallDirPath());
1376                // - java -cp 'DB-CLASSPATH'
1377                // org.apache.derby.drda.NetworkServerControl start
1378                // < /dev/null > start_external_harvest_database.log 2>&1 &
1379                startDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1380                // FIXME: Incomplete implementation of NAS-2030
1381                // startDBPrint.print("-Dderby.system.home="
1382                // + getInstallDirPath() + Constants.SLASH
1383                // + dbDir
1384                // + Constants.SPACE);
1385
1386                startDBPrint.print(machineParameters.writeJavaOptions());
1387                startDBPrint.print(Constants.SPACE);
1388                startDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1389                startDBPrint.print(Constants.SPACE + getDbClasspaths());
1390                startDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1391                // insert the PORT if any specified.
1392                if (port != null && !port.isEmpty()) {
1393                    startDBPrint.print(Constants.SPACE);
1394                    startDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1395                    startDBPrint.print(Constants.SPACE);
1396                    startDBPrint.print(port);
1397                }
1398                startDBPrint.print(Constants.SPACE);
1399                startDBPrint.print(ScriptConstants.DERBY_COMMAND_START);
1400                startDBPrint.print(Constants.SPACE);
1401                startDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1402                startDBPrint.print(Constants.SPACE);
1403                startDBPrint.print(Constants.SCRIPT_NAME_HARVEST_DB_START);
1404                startDBPrint.print(Constants.EXTENSION_LOG_FILES);
1405                startDBPrint.print(Constants.SPACE);
1406                startDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1407            } finally {
1408                // close file
1409                startDBPrint.close();
1410            }
1411        } catch (IOException e) {
1412            // Log the error and throw an IOFailure.
1413            log.trace(Constants.MSG_ERROR_DB_START_FILE, e);
1414            throw new IOFailure(Constants.MSG_ERROR_DB_START_FILE, e);
1415        }
1416    }
1417
1418    /**
1419     * Method for generating the command for running the external_harvest_database_start script. This should be called
1420     * before the application on the machines have been started.
1421     * <p>
1422     * <br/>
1423     * &gt; echo Starting external harvest database <br/>
1424     * &gt; if [ -e ./start_external_harvest_database.sh ]; then <br/>
1425     * &gt; ./start_external_harvest_database.sh & <br/>
1426     * &gt; sleep 5 <br/>
1427     * &gt; fi
1428     *
1429     * @return The command for running external_harvest_database_start script.
1430     */
1431    protected String callStartHarvestDatabase() {
1432        // Ignore if no archive database directory has been defined.
1433        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1434        if (dbDir.isEmpty()) {
1435            return "";
1436        }
1437
1438        // Constructing filename
1439        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_HARVEST_DB_START + scriptExtension;
1440
1441        //String app2Script = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_HARVEST_DB_UPDATE + scriptExtension;
1442        ;
1443
1444        StringBuilder res = new StringBuilder();
1445        // echo Starting external harvest database
1446        res.append(ScriptConstants.ECHO_START_EXTERNAL_HARVEST_DATABASE);
1447        res.append(Constants.NEWLINE);
1448        // if [ -e ./start_external_harvest_database.sh ]; then
1449        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1450        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1451        res.append(Constants.NEWLINE);
1452        // ./start_external_harvest_database.sh
1453        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1454        res.append(ScriptConstants.LINUX_RUN_BACKGROUND + Constants.NEWLINE);
1455        // sleep 5
1456        res.append(ScriptConstants.MULTI_SPACE_6 + ScriptConstants.SLEEP_5);
1457        // fi
1458        res.append(Constants.NEWLINE + ScriptConstants.FI);
1459        res.append(Constants.NEWLINE);
1460        // echo Updating external harvest database
1461        //res.append(ScriptConstants.ECHO_UPDATE_EXTERNAL_HARVEST_DATABASE);
1462        //res.append(Constants.NEWLINE);
1463        // if [ -e ./start_external_harvest_database.sh ]; then
1464        //res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1465        //res.append(app2Script + Constants.SPACE + ScriptConstants.LINUX_THEN);
1466        //res.append(Constants.NEWLINE);
1467        //res.append(ScriptConstants.MULTI_SPACE_6 + app2Script);
1468        //res.append(Constants.NEWLINE);
1469        //fi
1470        //res.append(ScriptConstants.FI + Constants.NEWLINE);
1471
1472        return res.toString();
1473    }
1474
1475    /**
1476     * Creates a script for killing the harvest database on a given machine. This is only created if the
1477     * &lt;globalHarvestDatabaseDir&gt; parameter is defined on the machine level.
1478     * <p>
1479     * The output is appended to the log, thus the '>>' instead of the standard '>' when redirecting the output.
1480     * <p>
1481     * <br/>
1482     * &gt; #!/bin/bash <br/>
1483     * &gt; cd InstallDir <br/>
1484     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl shutdown < /dev/null >>
1485     * start_external_harvest_database.log 2>&1 &
1486     * <p>
1487     * <br/>
1488     * where 'PORT' is in the setting: settings.common.database.port
1489     *
1490     * @param dir The directory where the script will be placed.
1491     * @throws IOFailure If the script cannot be created.
1492     */
1493    @Override
1494    protected void createHarvestDatabaseKillScript(File dir) throws IOFailure {
1495        // Ignore if no harvest database directory has been defined.
1496        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1497        if (dbDir.isEmpty()) {
1498            return;
1499        }
1500
1501        try {
1502            // initialise the script file.
1503            File killHarvestDBScript = new File(dir, Constants.SCRIPT_NAME_HARVEST_DB_KILL + scriptExtension);
1504
1505            // retrieve the port for the database.
1506            String port = settings.getLeafValue(Constants.SETTINGS_HARVEST_DATABASE_PORT);
1507
1508            // make print writer for writing to file
1509            PrintWriter killDBPrint = new PrintWriter(killHarvestDBScript, getTargetEncoding());
1510            try {
1511                // - #!/bin/bash
1512                killDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1513
1514                // - cd InstallDir
1515                killDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1516                killDBPrint.println(getInstallDirPath());
1517                // - java -cp 'DB-CLASSPATH'
1518                // org.apache.derby.drda.NetworkServerControl shutdown
1519                // < /dev/null >> start_external_harvest_database.log 2>&1 &
1520                killDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1521                killDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1522                killDBPrint.print(Constants.SPACE + getDbClasspaths());
1523                killDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1524                // insert the PORT if any specified.
1525                if (port != null && !port.isEmpty()) {
1526                    killDBPrint.print(Constants.SPACE);
1527                    killDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1528                    killDBPrint.print(Constants.SPACE);
1529                    killDBPrint.print(port);
1530                }
1531                killDBPrint.print(Constants.SPACE);
1532                killDBPrint.print(ScriptConstants.DERBY_COMMAND_KILL);
1533                killDBPrint.print(Constants.SPACE);
1534                killDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1535                killDBPrint.print(Constants.GREATER_THAN);
1536                killDBPrint.print(Constants.SPACE);
1537                killDBPrint.print(Constants.SCRIPT_NAME_HARVEST_DB_START);
1538                killDBPrint.print(Constants.EXTENSION_LOG_FILES);
1539                killDBPrint.print(Constants.SPACE);
1540                killDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1541            } finally {
1542                // close file
1543                killDBPrint.close();
1544            }
1545        } catch (IOException e) {
1546            // Log the error and throw an IOFailure.
1547            log.trace(Constants.MSG_ERROR_DB_KILL_FILE, e);
1548            throw new IOFailure(Constants.MSG_ERROR_DB_KILL_FILE, e);
1549        }
1550    }
1551
1552    /**
1553     * Method for generating the command for running the external_database_kill script. This should be called when the
1554     * application on the machines have been killed.
1555     * <p>
1556     * <br/>
1557     * &gt; echo Killing external harvest database <br/>
1558     * &gt; if [ -e ./kill_external_harvest_database.sh ]; then <br/>
1559     * &gt; ./kill_external_harvest_database.sh <br/>
1560     * &gt; fi
1561     *
1562     * @return The command for running external_harvest_database_kill script.
1563     */
1564    protected String callKillHarvestDatabase() {
1565        // Ignore if no harvest database directory has been defined.
1566        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1567        if (dbDir.isEmpty()) {
1568            return "";
1569        }
1570
1571        // Constructing filename
1572        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_HARVEST_DB_KILL + scriptExtension;
1573
1574        StringBuilder res = new StringBuilder();
1575        // echo Killing external harvest database
1576        res.append(ScriptConstants.ECHO_KILL_EXTERNAL_HARVEST_DATABASE);
1577        res.append(Constants.NEWLINE);
1578        // if [ -e ./kill_external_harvest_database.sh ]; then
1579        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1580        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1581        res.append(Constants.NEWLINE);
1582        // ./kill_external_harvest_database.sh
1583        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1584        res.append(Constants.NEWLINE);
1585        // fi
1586        res.append(ScriptConstants.FI + Constants.NEWLINE);
1587
1588        return res.toString();
1589    }
1590
1591    /**
1592     * Method for combining the classpaths for the database access. <br/>
1593     * E.g. /home/test/NAS/lib/db/derby.jar:/home/test/NAS/lib/db/derbynet.jar
1594     *
1595     * @return The combined classpaths for accessing the database.
1596     */
1597    private String getDbClasspaths() {
1598        StringBuilder res = new StringBuilder();
1599
1600        for (int i = 0; i < ScriptConstants.DERBY_ACCESS_CLASSPATH.length; i++) {
1601            // ignore colon at the first classpath.
1602            if (i != 0) {
1603                res.append(Constants.COLON);
1604            }
1605            res.append(getInstallDirPath() + Constants.SLASH);
1606            res.append(ScriptConstants.DERBY_ACCESS_CLASSPATH[i]);
1607        }
1608        res.append(Constants.SPACE);
1609        return res.toString();
1610    }
1611
1612    @Override
1613    protected void createHarvestDatabaseUpdateScript(File dir, boolean forceCreate) {
1614        // Ignore if no harvest database directory has been defined or this isn't a harvest server app.
1615        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1616        if (dbDir.isEmpty() && !forceCreate) {
1617            return;
1618        }
1619
1620        try {
1621            // initialise the script file.
1622            File updateHarvestDBScript = new File(dir, Constants.SCRIPT_NAME_HARVEST_DB_UPDATE + scriptExtension);
1623
1624            File updateHarvestDBSettingsFile = new File(dir, Constants.SETTINGS_PREFIX
1625                    + Constants.SCRIPT_NAME_HARVEST_DB_UPDATE + Constants.EXTENSION_XML_FILES);
1626            PrintWriter updateDBSettings = new PrintWriter(updateHarvestDBSettingsFile, getTargetEncoding());
1627            updateDBSettings.println(settings.getXML());
1628            updateDBSettings.close();
1629
1630            // make print writer for writing to file
1631            PrintWriter updateDBPrint = new PrintWriter(updateHarvestDBScript, getTargetEncoding());
1632            try {
1633                // - #!/bin/bash
1634                updateDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1635
1636                // - cd InstallDir
1637                updateDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1638                updateDBPrint.println(getInstallDirPath());
1639
1640                // - java -cp
1641                // org.apache.derby.drda.NetworkServerControl shutdown
1642                // < /dev/null >> start_external_harvest_database.log 2>&1 &
1643
1644                updateDBPrint.print(ScriptConstants.EXPORT_CLASSPATH);
1645                updateDBPrint.print(getHarvestServerClasspath() + getHarvesterCoreClasspath() + ScriptConstants.NEWLINE);
1646
1647                updateDBPrint.print(ScriptConstants.JAVA + Constants.SPACE + "-" + ScriptConstants.OPTION_SETTINGS
1648                        + getConfDirPath() + updateHarvestDBSettingsFile.getName() + Constants.SPACE);
1649                updateDBPrint.print(ScriptConstants.HARVEST_DATABASE_UPDATE_APP);
1650
1651                updateDBPrint.print(Constants.SPACE);
1652                updateDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1653                updateDBPrint.print(Constants.GREATER_THAN);
1654                updateDBPrint.print(Constants.SPACE);
1655                updateDBPrint.print(Constants.SCRIPT_NAME_HARVEST_DB_UPDATE);
1656                updateDBPrint.print(Constants.EXTENSION_LOG_FILES);
1657                updateDBPrint.print(Constants.SPACE);
1658                updateDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1659            } finally {
1660                // close file
1661                updateDBPrint.close();
1662            }
1663        } catch (IOException e) {
1664            // Log the error and throw an IOFailure.
1665            log.trace(Constants.MSG_ERROR_DB_KILL_FILE, e);
1666            throw new IOFailure(Constants.MSG_ERROR_DB_KILL_FILE, e);
1667        }
1668    }
1669
1670    private String getDefaultMachineClasspath() {
1671        StringBuilder res = new StringBuilder();
1672        // get all the classpaths
1673        for (Element cp : machineParameters.getClassPaths()) {
1674            res.append(getInstallDirPath() + Constants.SLASH + cp.getText().trim() + Constants.COLON);
1675        }
1676        return res.toString();
1677    }
1678
1679    private String getHarvestServerClasspath() {
1680        return getDefaultMachineClasspath() +
1681                getInstallDirPath() + Constants.SLASH + "lib/netarchivesuite-harvest-scheduler.jar" + Constants.COLON;
1682    }
1683
1684    private String getHarvesterCoreClasspath() {
1685        return getDefaultMachineClasspath() +
1686                getInstallDirPath() + Constants.SLASH + "lib/netarchivesuite-harvester-core.jar" + Constants.COLON;
1687    }
1688
1689
1690    @Override
1691    protected String getLibDirPath() {
1692        return getInstallDirPath() + Constants.LIB_DIR_LINUX;
1693    }
1694
1695        @Override
1696        protected String osUpdateLogos() {
1697                if (logoFile == null && menulogoFile == null) {
1698                        return "";
1699                }
1700                
1701                StringBuilder res = new StringBuilder();
1702                
1703        res.append(ScriptConstants.ECHO_CHANGING_LOGOS);
1704        res.append(Constants.NEWLINE);
1705
1706        if (logoFile != null) {
1707                res = updateLogofileInWarFiles(res, logoFile, Constants.DEFAULT_LOGO_FILENAME);         
1708        }
1709        
1710        if (menulogoFile != null) {
1711                res = updateLogofileInWarFiles(res, menulogoFile, Constants.DEFAULT_MENULOGO_FILENAME);         
1712        }
1713        
1714        return res.toString();
1715        }
1716
1717        @Override
1718    protected void copyBitmagClientConfig() {
1719        if (bitmagasinFolder == null) {
1720            return;
1721        }
1722        File targetFolder = new File(machineDirectory, Constants.BITMAG_CLIENT_CONFIG_DIR);
1723        FileUtils.createDir(targetFolder);
1724        File targetPemFile = new File(targetFolder, Constants.BITMAG_CERTKEY_FILE);
1725        for (File sourceFile: bitmagasinFolder.listFiles()) {
1726            if (sourceFile.getName().endsWith(".pem")) {
1727                FileUtils.copyFile(sourceFile, targetPemFile);
1728            } else {
1729                FileUtils.copyFile(sourceFile, new File(targetFolder, sourceFile.getName()));
1730            }
1731        }
1732    }
1733
1734}