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() != null) {
084                    bundlesArr = new String[] { deployConfiguration.getDefaultBundlerZip().getAbsolutePath() };
085                } else if ((bundlesArr == null || bundlesArr.length == 0 || bundlesArr[0].length()==0)
086                        && deployConfiguration.getDefaultBundlerZip() == null) {
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_HERITRIX3_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            if (app.getTotalName().contains("GUI")) {
547                 createHarvestDatabaseUpdateScript(directory, true);
548            }
549            File appStartScript = new File(directory, Constants.SCRIPT_NAME_LOCAL_START + app.getIdentification()
550                    + scriptExtension);
551            try {
552                // make print writer for writing to file
553                PrintWriter appPrint = new PrintWriter(appStartScript, getTargetEncoding());
554                try {
555                    // #!/bin/bash
556                    appPrint.println(ScriptConstants.ECHO_START_LINUX_APP + Constants.COLON + Constants.SPACE
557                            + app.getIdentification());
558                    // cd path
559                    appPrint.println(ScriptConstants.CD + Constants.SPACE + app.installPathLinux());
560                    // PIDS = $(ps -wwfe | grep fullapp | grep -v grep | grep
561                    // path\settings_app.xml | awk "{print \\$2}")
562                    appPrint.println(ScriptConstants.getLinuxPIDS(app.getTotalName(), getConfDirPath(),
563                            app.getIdentification()));
564                    // if [ -n "$PIDS" ]; then
565                    appPrint.println(ScriptConstants.LINUX_IF_N_EXIST + Constants.SPACE + Constants.QUOTE_MARK
566                            + ScriptConstants.PIDS + Constants.QUOTE_MARK + Constants.SPACE
567                            + ScriptConstants.LINUX_N_THEN);
568                    // echo Application already running.
569                    appPrint.println(ScriptConstants.ECHO_APP_ALREADY_RUNNING);
570                    // else
571                    appPrint.println(ScriptConstants.ELSE);
572                    // export CLASSPATH = cp;
573                    appPrint.println(ScriptConstants.MULTI_SPACE_4 + ScriptConstants.EXPORT_CLASSPATH
574                            + osGetClassPath(app) + ScriptConstants.VALUE_OF_CLASSPATH + Constants.SEMICOLON);
575                    // JAVA
576                    String securityManagement = "";
577                    if (app.getTotalName().contains(ScriptConstants.BITARCHIVE_APPLICATION_NAME)) {
578                        securityManagement = Constants.SPACE + Constants.DASH + ScriptConstants.OPTION_SECURITY_MANAGER
579                                + Constants.SPACE + Constants.DASH + ScriptConstants.OPTION_SECURITY_POLICY
580                                + getConfDirPath() + Constants.SECURITY_POLICY_FILE_NAME;
581                    }
582                    appPrint.println(ScriptConstants.MULTI_SPACE_4
583                            + ScriptConstants.JAVA
584                            + Constants.SPACE
585                            + app.getMachineParameters().writeJavaOptions()
586                            + Constants.SPACE
587                            + Constants.DASH
588                            + ScriptConstants.OPTION_SETTINGS
589                            + getConfDirPath()
590                            + Constants.PREFIX_SETTINGS
591                            + app.getIdentification()
592                            + Constants.EXTENSION_XML_FILES
593
594                            // TODO check to see if inheritedSlf4jConfigFile is not null
595                            + Constants.SPACE + Constants.DASH + ScriptConstants.OPTION_LOGBACK_CONFIG
596                            + getConfDirPath() + Constants.LOGBACK_PREFIX + app.getIdentification()
597                            + Constants.EXTENSION_XML_FILES
598
599                            + securityManagement
600
601                            + Constants.SPACE + app.getTotalName() + Constants.SPACE + ScriptConstants.LINUX_DEV_NULL
602                            + Constants.SPACE + Constants.SCRIPT_NAME_LOCAL_START + app.getIdentification()
603                            + Constants.EXTENSION_LOG_FILES + Constants.SPACE
604                            + ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
605                    // fi
606                    appPrint.println(ScriptConstants.FI);
607                } finally {
608                    // close file
609                    appPrint.close();
610                }
611            } catch (IOException e) {
612                String msg = "Problems creating application start script. ";
613                log.trace(msg, e);
614                throw new IOFailure(msg, e);
615            }
616        }
617    }
618
619    @Override
620    protected String osGetClassPath(Application app) {
621        StringBuilder res = new StringBuilder();
622        // get all the classpaths
623        for (Element cp : app.getMachineParameters().getClassPaths()) {
624            res.append(getInstallDirPath() + Constants.SLASH + cp.getText().trim() + Constants.COLON);
625        }
626        return res.toString();
627    }
628
629    @Override
630    protected String osInstallDatabase() {
631        StringBuilder res = new StringBuilder();
632
633        String databaseDir = machineParameters.getHarvestDatabaseDirValue();
634        // Do not install if no proper database directory.
635        if (databaseDir == null || databaseDir.isEmpty()) {
636            return Constants.EMPTY;
637        }
638
639        // copy to final destination if database argument.
640        if (databaseFile != null) {
641            // echo Copying database
642            res.append(ScriptConstants.ECHO_COPYING_DATABASE);
643            res.append(Constants.NEWLINE);
644            // scp database.jar user@machine:dbDir/db
645            res.append(ScriptConstants.SCP + Constants.SPACE);
646            res.append(databaseFile.getPath());
647            res.append(Constants.SPACE);
648            res.append(machineUserLogin());
649            res.append(Constants.COLON);
650            res.append(getInstallDirPath());
651            res.append(Constants.SLASH);
652            res.append(Constants.HARVEST_DATABASE_BASE_PATH);
653            res.append(Constants.NEWLINE);
654        }
655        // unzip database.
656        res.append(ScriptConstants.ECHO_UNZIPPING_DATABASE);
657        res.append(Constants.NEWLINE);
658        // ssh user@machine "
659        // cd dir; if [ -d databaseDir ]; then echo ;
660        // else mkdir databaseDir; fi; if [ $(ls -A databaseDir) ];
661        // then echo ERROR MESSAGE: DIR NOT EMPTY;
662        // else unzip -q -o dbDir/db -d databaseDir/.; fi; exit;
663        // "
664        res.append(ScriptConstants.SSH + Constants.SPACE);
665        res.append(machineUserLogin());
666        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.CD + Constants.SPACE);
667        res.append(getInstallDirPath());
668        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.LINUX_IF_DIR_EXIST + Constants.SPACE);
669        res.append(databaseDir);
670        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.ECHO
671                + Constants.SPACE);
672        res.append(ScriptConstants.DATABASE_ERROR_PROMPT_DIR_NOT_EMPTY);
673        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.ELSE + Constants.SPACE
674                + ScriptConstants.LINUX_UNZIP_COMMAND + Constants.SPACE);
675        res.append(Constants.HARVEST_DATABASE_BASE_PATH);
676        res.append(Constants.SPACE + ScriptConstants.SCRIPT_DIR + Constants.SPACE);
677        res.append(databaseDir);
678        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.FI + Constants.SEMICOLON + Constants.SPACE
679                + ScriptConstants.EXIT + Constants.SEMICOLON + Constants.SPACE + Constants.QUOTE_MARK);
680        res.append(Constants.NEWLINE);
681
682        return res.toString();
683    }
684
685    @Override
686    protected String osInstallExternalJarFiles() {
687        if (jarFolder == null) {
688            return Constants.EMPTY;
689        }
690
691        StringBuilder res = new StringBuilder();
692
693        // Comment about copying files.
694        res.append(ScriptConstants.ECHO_INSTALLING_EXTERNAL_JAR_FILES);
695        res.append(Constants.NEWLINE);
696        // if [ -d folder ]; then scp folder machine:installdir/external; fi;
697        res.append(ScriptConstants.LINUX_IF_DIR_EXIST + Constants.SPACE);
698        res.append(jarFolder.getPath());
699        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.SCP
700                + Constants.SPACE + ScriptConstants.DASH_R + Constants.SPACE);
701        res.append(jarFolder.getPath());
702        res.append(Constants.SPACE);
703        res.append(machineUserLogin());
704        res.append(Constants.COLON);
705        res.append(getInstallDirPath());
706        res.append(Constants.SLASH + Constants.EXTERNAL_JAR_DIRECTORY + Constants.SEMICOLON + Constants.SPACE
707                + ScriptConstants.FI + Constants.SEMICOLON);
708        res.append(Constants.NEWLINE);
709
710        return res.toString();
711    }
712
713    @Override
714    protected String osInstallArchiveDatabase() {
715        String adminDatabaseDir = machineParameters.getArchiveDatabaseDirValue();
716        // Do not install if no proper archive database directory.
717        if (adminDatabaseDir == null || adminDatabaseDir.isEmpty()) {
718            return Constants.EMPTY;
719        }
720
721        // Initialise the StringBuilder containing the resulting script.
722        StringBuilder res = new StringBuilder();
723
724        // copy to final destination if database argument.
725        if (arcDatabaseFile != null) {
726            // echo Copying database
727            res.append(ScriptConstants.ECHO_COPYING_ARCHIVE_DATABASE);
728            res.append(Constants.NEWLINE);
729            // scp database.jar user@machine:dbDir/bpdb
730            res.append(ScriptConstants.SCP + Constants.SPACE);
731            res.append(arcDatabaseFile.getPath());
732            res.append(Constants.SPACE);
733            res.append(machineUserLogin());
734            res.append(Constants.COLON);
735            res.append(getInstallDirPath());
736            res.append(Constants.SLASH);
737            // Now the two databases are in different directories
738            res.append(Constants.ARCHIVE_DATABASE_BASE_PATH);
739            res.append(Constants.NEWLINE);
740        }
741        // unzip database.
742        res.append(ScriptConstants.ECHO_UNZIPPING_ARCHIVE_DATABASE);
743        res.append(Constants.NEWLINE);
744        // ssh user@machine "
745        // cd dir; if [ -d bpDatabaseDir ]; then echo ;
746        // else mkdir bpDatabaseDir; fi; if [ $(ls -A bpDatabaseDir) ];
747        // then echo ERROR MESSAGE: DIR NOT EMPTY;
748        // else unzip -q -o dbDir/bpdb -d databaseDir/.; fi; exit;
749        // "
750        res.append(ScriptConstants.SSH + Constants.SPACE);
751        res.append(machineUserLogin());
752        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.CD + Constants.SPACE);
753        res.append(getInstallDirPath());
754        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.LINUX_IF_DIR_EXIST + Constants.SPACE);
755        res.append(adminDatabaseDir);
756        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.ECHO
757                + Constants.SPACE);
758        res.append(ScriptConstants.DATABASE_ERROR_PROMPT_DIR_NOT_EMPTY);
759        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.ELSE + Constants.SPACE
760                + ScriptConstants.LINUX_UNZIP_COMMAND + Constants.SPACE);
761        res.append(Constants.ARCHIVE_DATABASE_BASE_PATH);
762        res.append(Constants.SPACE + ScriptConstants.SCRIPT_DIR + Constants.SPACE);
763        res.append(adminDatabaseDir);
764        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.FI + Constants.SEMICOLON + Constants.SPACE
765                + ScriptConstants.EXIT + Constants.SEMICOLON + Constants.SPACE + Constants.QUOTE_MARK);
766        res.append(Constants.NEWLINE);
767
768        return res.toString();
769    }
770
771    /**
772     * Creates the specified directories in the deploy-configuration file.
773     * <p>
774     * Structure - ssh login cd path; DIRS; CLEANDIR; exit;
775     * <p>
776     * where: login = username@machine. path = path to install directory. DIRS = the way to create directories. CLEANDIR
777     * = the command to clean the tempDir (if chosen as optional)
778     * <p>
779     * The install creation of DIR has the following structure for directory dir: if [ ! -d dir ]; then mkdir dir; fi;
780     *
781     * @return The script for creating the directories.
782     */
783    @Override
784    protected String osInstallScriptCreateDir() {
785        StringBuilder res = new StringBuilder();
786        res.append(ScriptConstants.ECHO_CREATING_DIRECTORIES);
787        res.append(Constants.NEWLINE);
788        res.append(ScriptConstants.SSH + Constants.SPACE);
789        res.append(machineUserLogin());
790        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.CD + Constants.SPACE);
791        res.append(getInstallDirPath());
792        res.append(Constants.SEMICOLON + Constants.SPACE);
793
794        // go through all directories.
795        String dir;
796
797        // get archive.bitpresevation.baseDir directory.
798        dir = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_BP_BASEDIR_LEAF);
799        if (dir != null && !dir.isEmpty() && !dir.equalsIgnoreCase(Constants.DOT)) {
800            res.append(createPathToDir(dir));
801            res.append(scriptCreateDir(dir, false));
802        }
803
804        // get archive.arcrepository.baseDir directory.
805        dir = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_ARC_BASEDIR_LEAF);
806        if (dir != null && !dir.isEmpty() && !dir.equalsIgnoreCase(Constants.DOT)) {
807            res.append(scriptCreateDir(dir, false));
808        }
809
810        // get tempDir directory.
811        dir = settings.getLeafValue(Constants.SETTINGS_TEMPDIR_LEAF);
812        if (dir != null && !dir.isEmpty() && !dir.equalsIgnoreCase(Constants.DOT)) {
813            res.append(createPathToDir(dir));
814            res.append(scriptCreateDir(dir, resetTempDir));
815        }
816
817        // get the application specific directories.
818        res.append(getAppDirectories());
819
820        res.append(ScriptConstants.EXIT + Constants.SEMICOLON + Constants.SPACE + Constants.QUOTE_MARK
821                + Constants.NEWLINE);
822
823        return res.toString();
824    }
825
826    @Override
827    protected String scriptCreateDir(String dir, boolean clean) {
828        StringBuilder res = new StringBuilder();
829        res.append(ScriptConstants.LINUX_IF_NOT_DIR_EXIST + Constants.SPACE);
830        res.append(dir);
831        res.append(Constants.SPACE + ScriptConstants.LINUX_THEN + Constants.SPACE + ScriptConstants.MKDIR
832                + Constants.SPACE);
833        res.append(dir);
834        if (clean) {
835            res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.ELSE_REMOVE + Constants.SPACE);
836            res.append(dir);
837            res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.MKDIR + Constants.SPACE);
838            res.append(dir);
839        }
840        res.append(Constants.SEMICOLON + Constants.SPACE + ScriptConstants.FI + Constants.SEMICOLON + Constants.SPACE);
841
842        return res.toString();
843    }
844
845    /**
846     * Function for creating the directories along the path until the end directory. Does not create the end directory.
847     *
848     * @param dir The path to the directory.
849     * @return The script for creating the directory.
850     */
851    protected String createPathToDir(String dir) {
852        StringBuilder res = new StringBuilder();
853
854        String[] pathDirs = dir.split(Constants.REGEX_SLASH_CHARACTER);
855        StringBuilder path = new StringBuilder();
856
857        // only make directories along path to last directory,
858        // don't create end directory.
859        for (int i = 0; i < pathDirs.length - 1; i++) {
860            // don't make directory of empty path.
861            if (!pathDirs[i].isEmpty()) {
862                path.append(pathDirs[i]);
863                res.append(scriptCreateDir(path.toString(), false));
864            }
865            path.append(Constants.SLASH);
866        }
867
868        return res.toString();
869    }
870
871    @Override
872    protected String getAppDirectories() {
873        StringBuilder res = new StringBuilder();
874        String[] dirs;
875
876        for (Application app : applications) {
877            // get archive.fileDir directories.
878            dirs = app.getSettingsValues(Constants.SETTINGS_BITARCHIVE_BASEFILEDIR_LEAF);
879            if (dirs != null && dirs.length > 0) {
880                for (String dir : dirs) {
881                    res.append(createPathToDir(dir));
882                    res.append(scriptCreateDir(dir, false));
883                    for (String subdir : Constants.BASEFILEDIR_SUBDIRECTORIES) {
884                        res.append(scriptCreateDir(dir + Constants.SLASH + subdir, false));
885                    }
886                }
887            }
888
889            // get harvester.harvesting.serverDir directories.
890            dirs = app.getSettingsValues(Constants.SETTINGS_HARVEST_SERVERDIR_LEAF);
891            if (dirs != null && dirs.length > 0) {
892                for (String dir : dirs) {
893                    res.append(createPathToDir(dir));
894                    res.append(scriptCreateDir(dir, false));
895                }
896            }
897
898            // get the viewerproxy.baseDir directories.
899            dirs = app.getSettingsValues(Constants.SETTINGS_VIEWERPROXY_BASEDIR_LEAF);
900            if (dirs != null && dirs.length > 0) {
901                for (String dir : dirs) {
902                    res.append(createPathToDir(dir));
903                    res.append(scriptCreateDir(dir, false));
904                }
905            }
906
907            // get the common.tempDir directories. But only those,
908            // which are not the same as the machine common.tempDir.
909            dirs = app.getSettingsValues(Constants.SETTINGS_TEMPDIR_LEAF);
910            if (dirs != null && dirs.length > 0) {
911                String machineDir = settings.getLeafValue(Constants.SETTINGS_TEMPDIR_LEAF);
912                for (String dir : dirs) {
913                    // Don't make machine temp dir twice.
914                    if (!dir.equals(machineDir)) {
915                        res.append(createPathToDir(dir));
916                        res.append(scriptCreateDir(dir, resetTempDir));
917                    }
918                }
919            }
920        }
921
922        return res.toString();
923    }
924
925    /**
926     * Dummy function on linux machine. This is only used for windows machines!
927     *
928     * @param dir The directory to put the file.
929     */
930    @Override
931    protected void createInstallDirScript(File dir) {
932        // Do nothing. Dummy function on linux machine.
933    }
934
935    @Override
936    protected String changeFileDirPathForSecurity(String path) {
937        path += Constants.SLASH + Constants.SECURITY_FILE_DIR_TAG + Constants.SLASH;
938        return path.replace(Constants.SLASH, ScriptConstants.SECURITY_DIR_SEPARATOR);
939    }
940
941    @Override
942    protected String getJMXremoteFilesCommand() {
943        String accessFilePath;
944        String passwordFilePath;
945        String[] options;
946
947        // retrieve the access file path.
948        options = settings.getLeafValues(Constants.SETTINGS_COMMON_JMX_ACCESSFILE);
949
950        // extract the path, if any. Else set default.
951        if (options.length == 0) {
952            accessFilePath = Constants.JMX_ACCESS_FILE_PATH_DEFAULT;
953        } else {
954            accessFilePath = options[0];
955            // warn if more than one access file is defined.
956            if (options.length > 1) {
957                log.debug(Constants.MSG_WARN_TOO_MANY_JMXREMOTE_FILE_PATHS);
958            }
959        }
960
961        // retrieve the password file path.
962        options = settings.getLeafValues(Constants.SETTINGS_COMMON_JMX_PASSWORDFILE);
963
964        // extract the path, if any. Else set default.
965        if (options.length == 0) {
966            passwordFilePath = Constants.JMX_PASSWORD_FILE_PATH_DEFAULT;
967        } else {
968            passwordFilePath = options[0];
969            // warn if more than one access file is defined.
970            if (options.length > 1) {
971                log.debug(Constants.MSG_WARN_TOO_MANY_JMXREMOTE_FILE_PATHS);
972            }
973        }
974
975        // initialise the resulting command string.
976        StringBuilder res = new StringBuilder();
977
978        // echo make password files readonly
979        res.append(ScriptConstants.ECHO_MAKE_PASSWORD_FILES);
980        res.append(Constants.NEWLINE);
981
982        // IF NOT DEFAULT PATHS, THEN MAKE SCRIPT TO MOVE THE FILES.
983        if (!accessFilePath.equals(Constants.JMX_ACCESS_FILE_PATH_DEFAULT)) {
984            // ssh dev@kb-test-adm-001.kb.dk "mv -f
985            // installpath/conf/jmxremote.access installpath/accessFilePath"
986            res.append(ScriptConstants.SSH + Constants.SPACE);
987            res.append(machineUserLogin());
988            res.append(Constants.SPACE + Constants.QUOTE_MARK);
989            res.append(ScriptConstants.LINUX_FORCE_MOVE);
990            res.append(Constants.SPACE);
991            res.append(getInstallDirPath());
992            res.append(Constants.SLASH);
993            res.append(Constants.JMX_ACCESS_FILE_PATH_DEFAULT);
994            res.append(Constants.SPACE);
995            res.append(getInstallDirPath());
996            res.append(Constants.SLASH);
997            res.append(accessFilePath);
998            res.append(Constants.QUOTE_MARK);
999            res.append(Constants.NEWLINE);
1000        }
1001
1002        if (!passwordFilePath.equals(Constants.JMX_PASSWORD_FILE_PATH_DEFAULT)) {
1003            // ssh dev@kb-test-adm-001.kb.dk "mv -f
1004            // installpath/conf/jmxremote.access installpath/accessFilePath"
1005            res.append(ScriptConstants.SSH + Constants.SPACE);
1006            res.append(machineUserLogin());
1007            res.append(Constants.SPACE + Constants.QUOTE_MARK);
1008            res.append(ScriptConstants.LINUX_FORCE_MOVE);
1009            res.append(Constants.SPACE);
1010            res.append(getInstallDirPath());
1011            res.append(Constants.SLASH);
1012            res.append(Constants.JMX_PASSWORD_FILE_PATH_DEFAULT);
1013            res.append(Constants.SPACE);
1014            res.append(getInstallDirPath());
1015            res.append(Constants.SLASH);
1016            res.append(passwordFilePath);
1017            res.append(Constants.QUOTE_MARK);
1018            res.append(Constants.NEWLINE);
1019        }
1020
1021        // Allow only user to be able to only read jmxremote.password
1022        // (a=-rwx,u=+r) = 400.
1023        // ssh dev@kb-test-adm-001.kb.dk "chmod 400
1024        // /home/dev/TEST/conf/jmxremote.password"
1025        res.append(ScriptConstants.SSH + Constants.SPACE);
1026        res.append(machineUserLogin());
1027        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.LINUX_USER_400 + Constants.SPACE);
1028        res.append(getInstallDirPath());
1029        res.append(Constants.SLASH);
1030        res.append(passwordFilePath);
1031        res.append(Constants.QUOTE_MARK);
1032        res.append(Constants.NEWLINE);
1033        // ssh dev@kb-test-adm-001.kb.dk "chmod 400
1034        // /home/dev/TEST/conf/jmxremote.access"
1035        res.append(ScriptConstants.SSH + Constants.SPACE);
1036        res.append(machineUserLogin());
1037        res.append(Constants.SPACE + Constants.QUOTE_MARK + ScriptConstants.LINUX_USER_400 + Constants.SPACE);
1038        res.append(getInstallDirPath());
1039        res.append(Constants.SLASH);
1040        res.append(accessFilePath);
1041        res.append(Constants.QUOTE_MARK);
1042        res.append(Constants.NEWLINE);
1043
1044        return res.toString();
1045    }
1046
1047    /**
1048     * Creates script for restarting all the applications on a machine. This script should start by killing all the
1049     * existing processes, and then starting them again.
1050     * <p>
1051     * First the killall scripts is called, then wait for 5 seconds for the applications to be fully terminated, and
1052     * finally the startall script is called.
1053     *
1054     * @param dir The directory where the script file will be placed.
1055     * @throws IOFailure If the restart script cannot be created.
1056     */
1057    @Override
1058    protected void createRestartScript(File dir) throws IOFailure {
1059        try {
1060            // initialise the script file.
1061            File restartScript = new File(dir, Constants.SCRIPT_NAME_RESTART + scriptExtension);
1062
1063            // make print writer for writing to file
1064            PrintWriter restartPrint = new PrintWriter(restartScript, getTargetEncoding());
1065            try {
1066                // init, go to directory
1067                restartPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1068                restartPrint.println(ScriptConstants.CD + Constants.SPACE + getConfDirPath());
1069
1070                // call killall script.
1071                restartPrint.print(Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_KILL_ALL + scriptExtension);
1072                restartPrint.print(Constants.NEWLINE);
1073
1074                // call wait script.
1075                restartPrint.print(ScriptConstants.SLEEP);
1076                restartPrint.print(Constants.SPACE);
1077                restartPrint.print(Constants.WAIT_TIME_DURING_RESTART);
1078                restartPrint.print(Constants.NEWLINE);
1079
1080                // call startall script.
1081                restartPrint.print(Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_START_ALL + scriptExtension);
1082                restartPrint.print(Constants.NEWLINE);
1083            } finally {
1084                // close file
1085                restartPrint.close();
1086            }
1087        } catch (IOException e) {
1088            // Log the error and throw an IOFailure.
1089            log.trace(Constants.MSG_ERROR_RESTART_FILE, e);
1090            throw new IOFailure(Constants.MSG_ERROR_RESTART_FILE, e);
1091        }
1092    }
1093
1094    /**
1095     * Creates a script for starting the archive database on a given machine. This is only created if the
1096     * &lt;globalArchiveDatabaseDir&gt; parameter is defined on the machine level.
1097     * <p>
1098     * <br/>
1099     * &gt; #!/bin/bash <br/>
1100     * &gt; cd InstallDir <br/>
1101     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl start < /dev/null >
1102     * start_external_database.log 2>&1 &
1103     *
1104     * @param dir The directory where the script will be placed.
1105     * @throws IOFailure If the script cannot be written.
1106     */
1107    @Override
1108    protected void createArchiveDatabaseStartScript(File dir) throws IOFailure {
1109
1110        // Ignore if no archive database directory has been defined.
1111        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1112        if (dbDir.isEmpty()) {
1113            return;
1114        }
1115
1116        try {
1117            // initialise the script file.
1118            File startArcDBScript = new File(dir, Constants.SCRIPT_NAME_ADMIN_DB_START + scriptExtension);
1119
1120            // retrieve the port
1121            String port = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_DATABASE_PORT);
1122
1123            // make print writer for writing to file
1124            PrintWriter startDBPrint = new PrintWriter(startArcDBScript, getTargetEncoding());
1125            try {
1126                // - #!/bin/bash
1127                startDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1128                // - cd InstallDir
1129                startDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1130                startDBPrint.println(getInstallDirPath());
1131                // - java -Dderby.system.home=$INSTALLDIR/archivedatabasedir
1132                // -cp 'DB-CLASSPATH'
1133                // org.apache.derby.drda.NetworkServerControl start
1134                // < /dev/null > start_external_database.log 2>&1 &
1135                startDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1136                // FIXME: Incomplete implementation of NAS-2030
1137                // startDBPrint.print("-Dderby.system.home="
1138                // + getInstallDirPath() + Constants.SLASH
1139                // + dbDir
1140                // + Constants.SPACE);
1141
1142                startDBPrint.print(machineParameters.writeJavaOptions());
1143                startDBPrint.print(Constants.SPACE);
1144                startDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1145                startDBPrint.print(Constants.SPACE + getDbClasspaths());
1146                startDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1147                // insert the PORT if any specified.
1148                if (port != null && !port.isEmpty()) {
1149                    startDBPrint.print(Constants.SPACE);
1150                    startDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1151                    startDBPrint.print(Constants.SPACE);
1152                    startDBPrint.print(port);
1153                }
1154                startDBPrint.print(Constants.SPACE);
1155                startDBPrint.print(ScriptConstants.DERBY_COMMAND_START);
1156                startDBPrint.print(Constants.SPACE);
1157                startDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1158                startDBPrint.print(Constants.SPACE);
1159                startDBPrint.print(Constants.SCRIPT_NAME_ADMIN_DB_START);
1160                startDBPrint.print(Constants.EXTENSION_LOG_FILES);
1161                startDBPrint.print(Constants.SPACE);
1162                startDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1163            } finally {
1164                // close file
1165                startDBPrint.close();
1166            }
1167        } catch (IOException e) {
1168            // Log the error and throw an IOFailure.
1169            log.trace(Constants.MSG_ERROR_DB_START_FILE, e);
1170            throw new IOFailure(Constants.MSG_ERROR_DB_START_FILE, e);
1171        }
1172    }
1173
1174    /**
1175     * Method for generating the command for running the external_admin_database_start script. This should be called
1176     * before the application on the machines have been started.
1177     * <p>
1178     * <br/>
1179     * &gt; echo Starting external database <br/>
1180     * &gt; if [ -e ./start_external_admin_database.sh ]; then <br/>
1181     * &gt; ./start_external_admin_database.sh & <br/>
1182     * &gt; sleep 5 <br/>
1183     * &gt; fi
1184     *
1185     * @return The command for running external_admin_database_start script.
1186     */
1187    protected String callStartArchiveDatabase() {
1188        // Ignore if no archive database directory has been defined.
1189        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1190        if (dbDir.isEmpty()) {
1191            return "";
1192        }
1193
1194        // Constructing filename
1195        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_ADMIN_DB_START + scriptExtension;
1196
1197        StringBuilder res = new StringBuilder();
1198        // echo Starting external database
1199        res.append(ScriptConstants.ECHO_START_EXTERNAL_ADMIN_DATABASE);
1200        res.append(Constants.NEWLINE);
1201        // if [ -e ./start_external_database.sh ]; then
1202        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1203        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1204        res.append(Constants.NEWLINE);
1205        // ./start_external_database.sh
1206        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1207        res.append(ScriptConstants.LINUX_RUN_BACKGROUND + Constants.NEWLINE);
1208        // sleep 5
1209        res.append(ScriptConstants.MULTI_SPACE_6 + ScriptConstants.SLEEP_5);
1210        res.append(Constants.NEWLINE);
1211        // fi
1212        res.append(ScriptConstants.FI + Constants.NEWLINE);
1213
1214        return res.toString();
1215    }
1216
1217    /**
1218     * Creates a script for killing the archive database on a given machine. This is only created if the
1219     * &lt;globalArchiveDatabaseDir&gt; parameter is defined on the machine level.
1220     * <p>
1221     * The output is appended to the log, thus the '>>' instead of the standard '>' when redirecting the output.
1222     * <p>
1223     * <br/>
1224     * &gt; #!/bin/bash <br/>
1225     * &gt; cd InstallDir <br/>
1226     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl shutdown < /dev/null >>
1227     * start_external_database.log 2>&1 &
1228     * <p>
1229     * <br/>
1230     * where 'PORT' is in the setting: settings.archive.admin.database.port
1231     *
1232     * @param dir The directory where the script will be placed.
1233     * @throws IOFailure If the script cannot be created.
1234     */
1235    @Override
1236    protected void createArchiveDatabaseKillScript(File dir) throws IOFailure {
1237        // Ignore if no archive database directory has been defined.
1238        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1239        if (dbDir.isEmpty()) {
1240            return;
1241        }
1242
1243        try {
1244            // initialise the script file.
1245            File killArcDBScript = new File(dir, Constants.SCRIPT_NAME_ADMIN_DB_KILL + scriptExtension);
1246
1247            // retrieve the port for the database.
1248            String port = settings.getLeafValue(Constants.SETTINGS_ARCHIVE_DATABASE_PORT);
1249
1250            // make print writer for writing to file
1251            PrintWriter killDBPrint = new PrintWriter(killArcDBScript, getTargetEncoding());
1252            try {
1253                // - #!/bin/bash
1254                killDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1255
1256                // - cd InstallDir
1257                killDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1258                killDBPrint.println(getInstallDirPath());
1259                // - java -cp 'DB-CLASSPATH'
1260                // org.apache.derby.drda.NetworkServerControl shutdown
1261                // < /dev/null >> start_external_database.log 2>&1 &
1262                killDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1263                killDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1264                killDBPrint.print(Constants.SPACE + getDbClasspaths());
1265                killDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1266                // insert the PORT if any specified.
1267                if (port != null && !port.isEmpty()) {
1268                    killDBPrint.print(Constants.SPACE);
1269                    killDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1270                    killDBPrint.print(Constants.SPACE);
1271                    killDBPrint.print(port);
1272                }
1273                killDBPrint.print(Constants.SPACE);
1274                killDBPrint.print(ScriptConstants.DERBY_COMMAND_KILL);
1275                killDBPrint.print(Constants.SPACE);
1276                killDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1277                killDBPrint.print(Constants.GREATER_THAN);
1278                killDBPrint.print(Constants.SPACE);
1279                killDBPrint.print(Constants.SCRIPT_NAME_ADMIN_DB_START);
1280                killDBPrint.print(Constants.EXTENSION_LOG_FILES);
1281                killDBPrint.print(Constants.SPACE);
1282                killDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1283            } finally {
1284                // close file
1285                killDBPrint.close();
1286            }
1287        } catch (IOException e) {
1288            // Log the error and throw an IOFailure.
1289            log.trace(Constants.MSG_ERROR_DB_KILL_FILE, e);
1290            throw new IOFailure(Constants.MSG_ERROR_DB_KILL_FILE, e);
1291        }
1292    }
1293
1294    /**
1295     * Method for generating the command for running the external_database_kill script. This should be called when the
1296     * application on the machines have been killed.
1297     * <p>
1298     * <br/>
1299     * &gt; echo Killing external database <br/>
1300     * &gt; if [ -e ./kill_external_database.sh ]; then <br/>
1301     * &gt; ./kill_external_database.sh <br/>
1302     * &gt; fi
1303     *
1304     * @return The command for running external_database_kill script.
1305     */
1306    protected String callKillArchiveDatabase() {
1307        // Ignore if no archive database directory has been defined.
1308        String dbDir = machineParameters.getArchiveDatabaseDirValue();
1309        if (dbDir.isEmpty()) {
1310            return "";
1311        }
1312
1313        // Constructing filename
1314        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_ADMIN_DB_KILL + scriptExtension;
1315
1316        StringBuilder res = new StringBuilder();
1317        // echo Killing external database
1318        res.append(ScriptConstants.ECHO_KILL_EXTERNAL_ADMIN_DATABASE);
1319        res.append(Constants.NEWLINE);
1320        // if [ -e ./kill_external_database.sh ]; then
1321        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1322        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1323        res.append(Constants.NEWLINE);
1324        // ./kill_external_database.sh
1325        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1326        res.append(Constants.NEWLINE);
1327        // fi
1328        res.append(ScriptConstants.FI + Constants.NEWLINE);
1329
1330        return res.toString();
1331    }
1332
1333    /**
1334     * Creates a script for starting the harvest database on a given machine. This is only created if the
1335     * &lt;deployHarvestDatabaseDir&gt; parameter is defined on the machine level.
1336     * <p>
1337     * <br/>
1338     * &gt; #!/bin/bash <br/>
1339     * &gt; cd InstallDir <br/>
1340     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl start < /dev/null >
1341     * start_external_harvest_database.log 2>&1 &
1342     *
1343     * @param dir The directory where the script will be placed.
1344     * @throws IOFailure If the script cannot be written.
1345     */
1346    @Override
1347    protected void createHarvestDatabaseStartScript(File dir) throws IOFailure {
1348        // Ignore if no harvest database directory has been defined.
1349        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1350        if (dbDir.isEmpty()) {
1351            return;
1352        }
1353
1354        try {
1355            // initialise the script file.
1356            File startHarvestDBScript = new File(dir, Constants.SCRIPT_NAME_HARVEST_DB_START + scriptExtension);
1357
1358            // retrieve the port
1359            String port = settings.getLeafValue(Constants.SETTINGS_HARVEST_DATABASE_PORT);
1360
1361            // make print writer for writing to file
1362            PrintWriter startDBPrint = new PrintWriter(startHarvestDBScript, getTargetEncoding());
1363            try {
1364                // - #!/bin/bash
1365                startDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1366                // - cd InstallDir
1367                startDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1368                startDBPrint.println(getInstallDirPath());
1369                // - java -cp 'DB-CLASSPATH'
1370                // org.apache.derby.drda.NetworkServerControl start
1371                // < /dev/null > start_external_harvest_database.log 2>&1 &
1372                startDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1373                // FIXME: Incomplete implementation of NAS-2030
1374                // startDBPrint.print("-Dderby.system.home="
1375                // + getInstallDirPath() + Constants.SLASH
1376                // + dbDir
1377                // + Constants.SPACE);
1378
1379                startDBPrint.print(machineParameters.writeJavaOptions());
1380                startDBPrint.print(Constants.SPACE);
1381                startDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1382                startDBPrint.print(Constants.SPACE + getDbClasspaths());
1383                startDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1384                // insert the PORT if any specified.
1385                if (port != null && !port.isEmpty()) {
1386                    startDBPrint.print(Constants.SPACE);
1387                    startDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1388                    startDBPrint.print(Constants.SPACE);
1389                    startDBPrint.print(port);
1390                }
1391                startDBPrint.print(Constants.SPACE);
1392                startDBPrint.print(ScriptConstants.DERBY_COMMAND_START);
1393                startDBPrint.print(Constants.SPACE);
1394                startDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1395                startDBPrint.print(Constants.SPACE);
1396                startDBPrint.print(Constants.SCRIPT_NAME_HARVEST_DB_START);
1397                startDBPrint.print(Constants.EXTENSION_LOG_FILES);
1398                startDBPrint.print(Constants.SPACE);
1399                startDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1400            } finally {
1401                // close file
1402                startDBPrint.close();
1403            }
1404        } catch (IOException e) {
1405            // Log the error and throw an IOFailure.
1406            log.trace(Constants.MSG_ERROR_DB_START_FILE, e);
1407            throw new IOFailure(Constants.MSG_ERROR_DB_START_FILE, e);
1408        }
1409    }
1410
1411    /**
1412     * Method for generating the command for running the external_harvest_database_start script. This should be called
1413     * before the application on the machines have been started.
1414     * <p>
1415     * <br/>
1416     * &gt; echo Starting external harvest database <br/>
1417     * &gt; if [ -e ./start_external_harvest_database.sh ]; then <br/>
1418     * &gt; ./start_external_harvest_database.sh & <br/>
1419     * &gt; sleep 5 <br/>
1420     * &gt; fi
1421     *
1422     * @return The command for running external_harvest_database_start script.
1423     */
1424    protected String callStartHarvestDatabase() {
1425        // Ignore if no archive database directory has been defined.
1426        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1427        if (dbDir.isEmpty()) {
1428            return "";
1429        }
1430
1431        // Constructing filename
1432        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_HARVEST_DB_START + scriptExtension;
1433
1434        //String app2Script = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_HARVEST_DB_UPDATE + scriptExtension;
1435        ;
1436
1437        StringBuilder res = new StringBuilder();
1438        // echo Starting external harvest database
1439        res.append(ScriptConstants.ECHO_START_EXTERNAL_HARVEST_DATABASE);
1440        res.append(Constants.NEWLINE);
1441        // if [ -e ./start_external_harvest_database.sh ]; then
1442        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1443        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1444        res.append(Constants.NEWLINE);
1445        // ./start_external_harvest_database.sh
1446        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1447        res.append(ScriptConstants.LINUX_RUN_BACKGROUND + Constants.NEWLINE);
1448        // sleep 5
1449        res.append(ScriptConstants.MULTI_SPACE_6 + ScriptConstants.SLEEP_5);
1450        // fi
1451        res.append(Constants.NEWLINE + ScriptConstants.FI);
1452        res.append(Constants.NEWLINE);
1453        // echo Updating external harvest database
1454        //res.append(ScriptConstants.ECHO_UPDATE_EXTERNAL_HARVEST_DATABASE);
1455        //res.append(Constants.NEWLINE);
1456        // if [ -e ./start_external_harvest_database.sh ]; then
1457        //res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1458        //res.append(app2Script + Constants.SPACE + ScriptConstants.LINUX_THEN);
1459        //res.append(Constants.NEWLINE);
1460        //res.append(ScriptConstants.MULTI_SPACE_6 + app2Script);
1461        //res.append(Constants.NEWLINE);
1462        //fi
1463        //res.append(ScriptConstants.FI + Constants.NEWLINE);
1464
1465        return res.toString();
1466    }
1467
1468    /**
1469     * Creates a script for killing the harvest database on a given machine. This is only created if the
1470     * &lt;globalHarvestDatabaseDir&gt; parameter is defined on the machine level.
1471     * <p>
1472     * The output is appended to the log, thus the '>>' instead of the standard '>' when redirecting the output.
1473     * <p>
1474     * <br/>
1475     * &gt; #!/bin/bash <br/>
1476     * &gt; cd InstallDir <br/>
1477     * &gt; java -cp 'DB-CLASSPATH' org.apache.derby.drda.NetworkServerControl shutdown < /dev/null >>
1478     * start_external_harvest_database.log 2>&1 &
1479     * <p>
1480     * <br/>
1481     * where 'PORT' is in the setting: settings.common.database.port
1482     *
1483     * @param dir The directory where the script will be placed.
1484     * @throws IOFailure If the script cannot be created.
1485     */
1486    @Override
1487    protected void createHarvestDatabaseKillScript(File dir) throws IOFailure {
1488        // Ignore if no harvest database directory has been defined.
1489        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1490        if (dbDir.isEmpty()) {
1491            return;
1492        }
1493
1494        try {
1495            // initialise the script file.
1496            File killHarvestDBScript = new File(dir, Constants.SCRIPT_NAME_HARVEST_DB_KILL + scriptExtension);
1497
1498            // retrieve the port for the database.
1499            String port = settings.getLeafValue(Constants.SETTINGS_HARVEST_DATABASE_PORT);
1500
1501            // make print writer for writing to file
1502            PrintWriter killDBPrint = new PrintWriter(killHarvestDBScript, getTargetEncoding());
1503            try {
1504                // - #!/bin/bash
1505                killDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1506
1507                // - cd InstallDir
1508                killDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1509                killDBPrint.println(getInstallDirPath());
1510                // - java -cp 'DB-CLASSPATH'
1511                // org.apache.derby.drda.NetworkServerControl shutdown
1512                // < /dev/null >> start_external_harvest_database.log 2>&1 &
1513                killDBPrint.print(ScriptConstants.JAVA + Constants.SPACE);
1514                killDBPrint.print(ScriptConstants.JAVA_CLASSPATH);
1515                killDBPrint.print(Constants.SPACE + getDbClasspaths());
1516                killDBPrint.print(ScriptConstants.DERBY_ACCESS_METHOD);
1517                // insert the PORT if any specified.
1518                if (port != null && !port.isEmpty()) {
1519                    killDBPrint.print(Constants.SPACE);
1520                    killDBPrint.print(ScriptConstants.DATABASE_PORT_ARGUMENT);
1521                    killDBPrint.print(Constants.SPACE);
1522                    killDBPrint.print(port);
1523                }
1524                killDBPrint.print(Constants.SPACE);
1525                killDBPrint.print(ScriptConstants.DERBY_COMMAND_KILL);
1526                killDBPrint.print(Constants.SPACE);
1527                killDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1528                killDBPrint.print(Constants.GREATER_THAN);
1529                killDBPrint.print(Constants.SPACE);
1530                killDBPrint.print(Constants.SCRIPT_NAME_HARVEST_DB_START);
1531                killDBPrint.print(Constants.EXTENSION_LOG_FILES);
1532                killDBPrint.print(Constants.SPACE);
1533                killDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1534            } finally {
1535                // close file
1536                killDBPrint.close();
1537            }
1538        } catch (IOException e) {
1539            // Log the error and throw an IOFailure.
1540            log.trace(Constants.MSG_ERROR_DB_KILL_FILE, e);
1541            throw new IOFailure(Constants.MSG_ERROR_DB_KILL_FILE, e);
1542        }
1543    }
1544
1545    /**
1546     * Method for generating the command for running the external_database_kill script. This should be called when the
1547     * application on the machines have been killed.
1548     * <p>
1549     * <br/>
1550     * &gt; echo Killing external harvest database <br/>
1551     * &gt; if [ -e ./kill_external_harvest_database.sh ]; then <br/>
1552     * &gt; ./kill_external_harvest_database.sh <br/>
1553     * &gt; fi
1554     *
1555     * @return The command for running external_harvest_database_kill script.
1556     */
1557    protected String callKillHarvestDatabase() {
1558        // Ignore if no harvest database directory has been defined.
1559        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1560        if (dbDir.isEmpty()) {
1561            return "";
1562        }
1563
1564        // Constructing filename
1565        String appScript = Constants.DOT + Constants.SLASH + Constants.SCRIPT_NAME_HARVEST_DB_KILL + scriptExtension;
1566
1567        StringBuilder res = new StringBuilder();
1568        // echo Killing external harvest database
1569        res.append(ScriptConstants.ECHO_KILL_EXTERNAL_HARVEST_DATABASE);
1570        res.append(Constants.NEWLINE);
1571        // if [ -e ./kill_external_harvest_database.sh ]; then
1572        res.append(ScriptConstants.LINUX_IF_EXIST + Constants.SPACE);
1573        res.append(appScript + Constants.SPACE + ScriptConstants.LINUX_THEN);
1574        res.append(Constants.NEWLINE);
1575        // ./kill_external_harvest_database.sh
1576        res.append(ScriptConstants.MULTI_SPACE_6 + appScript);
1577        res.append(Constants.NEWLINE);
1578        // fi
1579        res.append(ScriptConstants.FI + Constants.NEWLINE);
1580
1581        return res.toString();
1582    }
1583
1584    /**
1585     * Method for combining the classpaths for the database access. <br/>
1586     * E.g. /home/test/NAS/lib/db/derby.jar:/home/test/NAS/lib/db/derbynet.jar
1587     *
1588     * @return The combined classpaths for accessing the database.
1589     */
1590    private String getDbClasspaths() {
1591        StringBuilder res = new StringBuilder();
1592
1593        for (int i = 0; i < ScriptConstants.DERBY_ACCESS_CLASSPATH.length; i++) {
1594            // ignore colon at the first classpath.
1595            if (i != 0) {
1596                res.append(Constants.COLON);
1597            }
1598            res.append(getInstallDirPath() + Constants.SLASH);
1599            res.append(ScriptConstants.DERBY_ACCESS_CLASSPATH[i]);
1600        }
1601        res.append(Constants.SPACE);
1602        return res.toString();
1603    }
1604
1605    @Override
1606    protected void createHarvestDatabaseUpdateScript(File dir, boolean forceCreate) {
1607        // Ignore if no harvest database directory has been defined or this isn't a harvest server app.
1608        String dbDir = machineParameters.getHarvestDatabaseDirValue();
1609        if (dbDir.isEmpty() && !forceCreate) {
1610            return;
1611        }
1612
1613        try {
1614            // initialise the script file.
1615            File updateHarvestDBScript = new File(dir, Constants.SCRIPT_NAME_HARVEST_DB_UPDATE + scriptExtension);
1616
1617            File updateHarvestDBSettingsFile = new File(dir, Constants.SETTINGS_PREFIX
1618                    + Constants.SCRIPT_NAME_HARVEST_DB_UPDATE + Constants.EXTENSION_XML_FILES);
1619            PrintWriter updateDBSettings = new PrintWriter(updateHarvestDBSettingsFile, getTargetEncoding());
1620            updateDBSettings.println(settings.getXML());
1621            updateDBSettings.close();
1622
1623            // make print writer for writing to file
1624            PrintWriter updateDBPrint = new PrintWriter(updateHarvestDBScript, getTargetEncoding());
1625            try {
1626                // - #!/bin/bash
1627                updateDBPrint.println(ScriptConstants.BIN_BASH_COMMENT);
1628
1629                // - cd InstallDir
1630                updateDBPrint.print(ScriptConstants.CD + Constants.SPACE);
1631                updateDBPrint.println(getInstallDirPath());
1632
1633                // - java -cp
1634                // org.apache.derby.drda.NetworkServerControl shutdown
1635                // < /dev/null >> start_external_harvest_database.log 2>&1 &
1636
1637                updateDBPrint.print(ScriptConstants.EXPORT_CLASSPATH);
1638                updateDBPrint.print(getHarvestServerClasspath() + getHarvesterCoreClasspath() + ScriptConstants.NEWLINE);
1639
1640                updateDBPrint.print(ScriptConstants.JAVA + Constants.SPACE + "-" + ScriptConstants.OPTION_SETTINGS
1641                        + getConfDirPath() + updateHarvestDBSettingsFile.getName() + Constants.SPACE);
1642                updateDBPrint.print(ScriptConstants.HARVEST_DATABASE_UPDATE_APP);
1643
1644                updateDBPrint.print(Constants.SPACE);
1645                updateDBPrint.print(ScriptConstants.LINUX_DEV_NULL);
1646                updateDBPrint.print(Constants.GREATER_THAN);
1647                updateDBPrint.print(Constants.SPACE);
1648                updateDBPrint.print(Constants.SCRIPT_NAME_HARVEST_DB_UPDATE);
1649                updateDBPrint.print(Constants.EXTENSION_LOG_FILES);
1650                updateDBPrint.print(Constants.SPACE);
1651                updateDBPrint.println(ScriptConstants.LINUX_ERROR_MESSAGE_TO_1);
1652            } finally {
1653                // close file
1654                updateDBPrint.close();
1655            }
1656        } catch (IOException e) {
1657            // Log the error and throw an IOFailure.
1658            log.trace(Constants.MSG_ERROR_DB_KILL_FILE, e);
1659            throw new IOFailure(Constants.MSG_ERROR_DB_KILL_FILE, e);
1660        }
1661    }
1662
1663    private String getDefaultMachineClasspath() {
1664        StringBuilder res = new StringBuilder();
1665        // get all the classpaths
1666        for (Element cp : machineParameters.getClassPaths()) {
1667            res.append(getInstallDirPath() + Constants.SLASH + cp.getText().trim() + Constants.COLON);
1668        }
1669        return res.toString();
1670    }
1671
1672    private String getHarvestServerClasspath() {
1673        return getDefaultMachineClasspath() +
1674                getInstallDirPath() + Constants.SLASH + "lib/netarchivesuite-harvest-scheduler.jar" + Constants.COLON;
1675    }
1676
1677    private String getHarvesterCoreClasspath() {
1678        return getDefaultMachineClasspath() +
1679                getInstallDirPath() + Constants.SLASH + "lib/netarchivesuite-harvester-core.jar" + Constants.COLON;
1680    }
1681
1682
1683    @Override
1684    protected String getLibDirPath() {
1685        return getInstallDirPath() + Constants.LIB_DIR_LINUX;
1686    }
1687
1688}