Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * RHQ Management Platform
   * Copyright (C) 2010 Red Hat, Inc.
   * All rights reserved.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation version 2 of the License.
   *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 package org.rhq.bundle.ant.type;
 
 import java.io.File;
 import java.util.Set;
 
 import  org.apache.tools.ant.taskdefs.optional.unix.Symlink;

An Ant task that installs a system startup/shutdown service. Currently only Red Hat Linux versions are supported.

Author(s):
Ian Springer
 
 public class SystemServiceType extends AbstractBundleType {
     private static final String OS_NAME = System.getProperty("os.name");
     private static final File REDHAT_RELEASE_FILE = new File("/etc/redhat-release");
     private static final Set<CharacterREDHAT_RUN_LEVELS = new HashSet<Character>();
     static {
         for (char c = '0'c <= '6'c++) {
             .add(c);
         }
         // TODO: Add 's' and/or 'S' depending on the flavor of UNIX.
     }
     private static final File INIT_DIR = new File("/etc/init.d");
     private static final File SYSCONFIG_DIR = new File("/etc/sysconfig");
     private static final File DEFAULT_ROOT = new File("/");
 
     private String name;
     private File scriptFile;
     private File configFile;
     private String scriptFileName;
     private String configFileName;
     private boolean overwriteScript;
     private boolean overwriteConfig;
     private boolean overwriteLinks = true;
     private File root = ;
     private String startLevels;

    
An integer from 0-99 indicating the service's start order - services with a lower priority number are started before services with a higher priority number.
 
     private Byte startPriority;

    
An integer from 0-99 indicating the service's stop order - services with a lower priority number are stopped before services with a higher priority number.
 
     private Byte stopPriority;
 
     private Set<CharacterstartLevelChars;
     private Set<CharacterstopLevelChars;
 
     private File scriptDestFile;
     private File configDestFile;
 
     public void validate() throws BuildException {
         validateAttributes();
 
         this. = new File(getInitDir(), this.);
         this. = new File(getSysConfigDir(), this.);
     }
 
     public void init() throws BuildException {
         if (!"Linux".equals() || !.exists()) {
             throw new BuildException("The system-service element is only supported on Red Hat Linux systems.");
         }
 
         if (!this..exists() || this..isDirectory()) {
             throw new BuildException("The 'scriptFile' attribute must be set to the path of an existing regular file.");
         }
         if (this. != null && (!this..exists() || this..isDirectory())) {
             throw new BuildException("The 'configFile' attribute must be set to the path of an existing regular file.");
         }
    }
    public void install() throws BuildException {
        // Install the config file if one was provided (e.g. /etc/sysconfig/named).
        if (this. != null) {
            File sysconfigDir = getSysConfigDir();
            if (!sysconfigDir.exists()) {
                sysconfigDir.mkdirs();
            }
            if (!sysconfigDir.canWrite()) {
                throw new BuildException(sysconfigDir + " directory is not writeable.");
            }
            // Don't copy the file ourselves - let our parent DeploymentUnitType handle it, so the deployment metadata
            // (i.e. MD5) can be calculated and saved.
            //copyFile(this.configFile, this.configDestFile, this.overwriteConfig);
            setPermissions(this."644");
        }
        // Install the script itself (e.g. /etc/init.d/named).
        File initDir = getInitDir();
        if (!initDir.exists()) {
            initDir.mkdirs();
        }
        if (!initDir.canWrite()) {
            throw new BuildException(initDir + " directory is not writeable.");
        }
        getProject().log("Installing service script " + this. + "...");
        // Don't copy the file ourselves - let our parent DeploymentUnitType handle it, so the deployment metadata
        // (i.e. MD5) can be calculated and saved.
        //copyFile(this.scriptFile, scriptDestFile, this.overwriteScript);
        setPermissions(this."755");
        // Create the symlinks in the rcX.d dirs (e.g. /etc/rc3.d/S24named -> ../init.d/named)
        createScriptSymlinks(this.this.this.'S');
        createScriptSymlinks(this.this.this.'K');
    }
    private File getInitDir() {
        return new File(this..getPath().substring(1));
    }
    public File getScriptDestFile() {
        return this.;
    }
    private File getSysConfigDir() {
        return new File(this..getPath().substring(1));
    }
    public File getConfigDestFile() {
        return this.;
    }
    public void start() throws BuildException {
        File scriptFile = getScriptDestFile();
        String[] commandLine = { scriptFile.getAbsolutePath(), "start" };
        try {
            executeCommand(commandLine);
        } catch (IOException e) {
            throw new BuildException("Failed to start " + this. + " system service via command ["
                + Arrays.toString(commandLine) + "]."e);
        }
    }
    public void stop() throws BuildException {
        File scriptFile = getScriptDestFile();
        String[] commandLine = { scriptFile.getAbsolutePath(), "stop" };
        try {
            executeCommand(commandLine);
        } catch (IOException e) {
            throw new BuildException("Failed to stop " + this. + " system service via command ["
                + Arrays.toString(commandLine) + "]."e);
        }
    }
    public void uninstall() throws BuildException {
        // TODO        
    }
    public String getName() {
        return ;
    }
    public void setName(String name) {
        this. = name;
    }
    public String getScriptFileName() {
        return ;
    }
    public File getScriptFile() {
        return ;
    }
    public void setScriptFile(String scriptFile) {
        File file = new File(scriptFile);
        if (file.isAbsolute()) {
            throw new BuildException("Path specified by 'scriptFile' attribute (" + scriptFile
                + ") is not relative - it must be a relative path, relative to the Ant basedir.");
        }
        this. = scriptFile;
        this. = getProject().resolveFile(scriptFile);
    }
    public String getConfigFileName() {
        return ;
    }
    public File getConfigFile() {
        return ;
    }
    public void setConfigFile(String configFile) {
        File file = new File(configFile);
        if (file.isAbsolute()) {
            throw new BuildException("Path specified by 'configFile' attribute (" + configFile
                + ") is not relative - it must be a relative path, relative to the Ant basedir.");
        }
        this. = configFile;
        this. = getProject().resolveFile(configFile);
    }
    public boolean isOverwriteScript() {
        return ;
    }
    public void setOverwriteScript(boolean overwriteScript) {
        this. = overwriteScript;
    }
    public boolean isOverwriteConfig() {
        return ;
    }
    public void setOverwriteConfig(boolean overwriteConfig) {
        this. = overwriteConfig;
    }
    public boolean isOverwriteLinks() {
        return ;
    }
    public void setOverwriteLinks(boolean overwriteLinks) {
        this. = overwriteLinks;
    }
    public String getStartLevels() {
        return ;
    }
    public void setStartLevels(String startLevels) {
        this. = startLevels;
    }
    public byte getStartPriority() {
        return ;
    }
    public void setStartPriority(byte startPriority) {
        this. = startPriority;
    }
    public byte getStopPriority() {
        return ;
    }
    public void setStopPriority(byte stopPriority) {
        this. = stopPriority;
    }
    public File getRoot() {
        return ;
    }
    public void setRoot(File root) {
        this. = root;
    }

    
Ensure we have a consistent and legal set of attributes, and set any internal flags necessary based on different combinations of attributes.

Throws:
BuildException if an error occurs
    protected void validateAttributes() throws BuildException {
        if (this. == null) {
            throw new BuildException("The 'name' attribute is required.");
        }
        if (this..length() == 0) {
            throw new BuildException("The 'name' attribute must have a non-empty value.");
        }
        if (this. == null) {
            throw new BuildException("The 'scriptFile' attribute is required.");
        }
        if (this. == null) {
            throw new BuildException("The 'startLevels' attribute is required.");
        }
        if (this..length() == 0) {
            throw new BuildException("The 'startLevels' attribute must have a non-empty value.");
        }
        this. = parseLevels(this.);
        this. = new TreeSet<Character>();
        for (char level : ) {
            if (!this..contains(level)) {
                this..add(level);
            }
        }
        if (this. == null) {
            throw new BuildException("The 'startPriority' attribute is required.");
        }
        if (this. < 0 || this. > 99) {
            throw new BuildException("The 'startPriority' attribute must be >=0 and <= 99.");
        }
        if (this. == null) {
            throw new BuildException("The 'stopPriority' attribute is required.");
        }
        if (this. < 0 || this. > 99) {
            throw new BuildException("The 'startPriority' attribute must be >=0 and <= 99.");
        }
        if (!this..exists()) {
            this..mkdirs();
            if (!this..exists()) {
                throw new BuildException("Failed to create root directory " + this.
                    + " as specified by 'root' attribute.");
            }
        }
        if (!this..isDirectory()) {
            throw new BuildException("The 'root' attribute must be set to the path of a directory.");
        }
        if (!this..equals()) {
            getProject().log("Using root " + this. + ".");
        }
    }
    private static Set<CharacterparseLevels(String levels) {
        Set<CharacterlevelChars = new TreeSet<Character>();
        String[] tokens = levels.split("[ ]*,[ ]*");
        for (String token : tokens) {
            if (!token.equals("")) {
                Character level;
                try {
                    if (token.length() != 1) {
                        throw new Exception();
                    }
                    level = token.charAt(0);
                    if (!.contains(level)) {
                        throw new Exception();
                    }
                } catch (Exception e) {
                    throw new BuildException(
                        "Invalid run level: "
                            + token
                            + " - the 'startLevels' attribute must be a comma-separated list of run levels - the valid levels are "
                            +  + ".");
                }
                if (levelChars.contains(level)) {
                    throw new BuildException("The 'startLevels' attribute defines run level " + level
                        + " more than once.");
                }
                levelChars.add(level);
            }
        }
        return levelChars;
    }
    private void createScriptSymlinks(File scriptFilebyte prioritySet<Characterlevelschar fileNamePrefix) {
        String priorityString = String.format("%02d"priority);
        for (char level : levels) {
            File rcDir = new File(this."etc/rc" + level + ".d");
            if (!rcDir.exists()) {
                rcDir.mkdirs();
            }
            if (!rcDir.exists()) {
                throw new BuildException(rcDir + " does not exist.");
            }
            if (!rcDir.isDirectory()) {
                throw new BuildException(rcDir + " exists but is not a directory.");
            }
            if (!rcDir.isDirectory()) {
                throw new BuildException(rcDir + " directory is not writeable.");
            }
            File link = new File(rcDirfileNamePrefix + priorityString + this.);
            getProject().log("Creating symbolic link " + link + " referencing " + scriptFile + "...");
            createSymlink(scriptFilelinkthis.);
        }
    }
    private void copyFile(File sourceFileFile destFileboolean overwrite) {
        Copy copyTask = new Copy();
        copyTask.setProject(getProject());
        copyTask.init();
        copyTask.setFile(sourceFile);
        copyTask.setTofile(destFile);
        copyTask.setOverwrite(overwrite);
        copyTask.execute();
    }
    private void createSymlink(File targetFileFile linkFileboolean overwrite) {
        Symlink symlinkTask = new Symlink();
        symlinkTask.setProject(getProject());
        symlinkTask.init();
        symlinkTask.setResource(targetFile.getAbsolutePath());
        symlinkTask.setLink(linkFile.getAbsolutePath());
        symlinkTask.setOverwrite(overwrite);
        symlinkTask.execute();
    }
    private int executeCommand(String[] commandLinethrows IOException {
        Execute executeTask = new Execute();
        executeTask.setCommandline(commandLine);
        return executeTask.execute();
    }
    private void setPermissions(File fileString perms) {
        Chmod chmodTask = new Chmod();
        chmodTask.setProject(getProject());
        chmodTask.init();
        chmodTask.setFile(file);
        chmodTask.setPerm(perms);
        chmodTask.execute();
    }
New to GrepCode? Check out our FAQ X