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