/*
* RHQ Management Platform
* Copyright (C) 2005-2013 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.enterprise.agent.update;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Properties;
import java.util.prefs.Preferences;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
/**
* This migrates agent preferences stored by the native preferences implementation to a file compatible with
* our custom FilePreferences implementation. It works as follows:
*
* @author Jay Shaughnessy
* @author John Mazzitelli
*/
public class MigrateAgentPreferences extends Task {
/**
* This is the top level parent node of all agent preferences and is directly under the userRoot preferences node.
*/
static private final String NODE_PARENT = "rhq-agent";
static private final String NODE_DELIM = "/";
static private final String NODE_PREFIX = NODE_PARENT + NODE_DELIM;
static private final String DEFAULT_PREFS_FILE = "agent-prefs.properties";
static private final String MAINTAIN_NATIVE_PREFS_SYSPROP = "rhq.preferences.migrate.keep-native-prefs";
// Currently keeping native prefs until we're sure we don't need them.
// static private final String MAINTAIN_NATIVE_PREFS_DEFAULT = "false";
static private final String MAINTAIN_NATIVE_PREFS_DEFAULT = "true";
static private final Boolean MAINTAIN_NATIVE_PREFS;
static {
MAINTAIN_NATIVE_PREFS = Boolean.valueOf(System.getProperty(MAINTAIN_NATIVE_PREFS_SYSPROP,
MAINTAIN_NATIVE_PREFS_DEFAULT));
}
private File toDir;
private Boolean failonerror = Boolean.FALSE;
public void setToDir(File toDir) {
this.toDir = toDir;
}
public void setFailonerror(Boolean flag) {
this.failonerror = flag;
}
/**
* @see org.apache.tools.ant.Task#execute()
*/
@Override
public void execute() throws BuildException {
validateAttributes();
try {
// if the prefs file already exists we can assume migration already happened or is unnecessary
String filePath = System.getProperty("rhq.preferences.file");
File toFile = (null != filePath) ? new File(filePath) : new File(toDir, DEFAULT_PREFS_FILE);
if (toFile.exists()) {
return;
}
Preferences userRoot = Preferences.userRoot();
// if there are no rhq-agent prefs stored then there is nothing to migrate
if (!userRoot.nodeExists(NODE_PARENT)) {
return;
}
Properties configProps = new Properties();
Preferences topNode = userRoot.node(NODE_PARENT);
// each --pref, including the default preferences are just one level down from the parent
for (String pref : topNode.childrenNames()) {
Preferences prefNode = topNode.node(pref);
for (String key : prefNode.keys()) {
String configPropKey = NODE_PREFIX + prefNode.name() + NODE_DELIM + key;
String configPropVal = prefNode.get(key, "");
configProps.setProperty(configPropKey, configPropVal);
}
}
// write out the new prefs file with the migrated properties
FileOutputStream fos = null;
try {
fos = new FileOutputStream(toFile);
configProps.store(fos, "Created by RHQ MigrateAgentPreferences tool.");
} finally {
if (null != fos) {
fos.close();
}
}
// wipe the old prefs to leave a clean system. In general there will only be one --pref child node,
// typically "default". Which means only one agent is actually configured under the "rhq-agent" top node.
// So, cleaning up and removing the top node should be preferable as it removes litter in the native prefs.
// If for some unlikely reason multiple agents are configured (using multiple --pref settings) then the user
// can avoid this cleanup by setting the proper system prop.
if (!MAINTAIN_NATIVE_PREFS) {
topNode.removeNode();
}
} catch (Throwable e) {
if (failonerror.booleanValue()) {
throw new BuildException(e);
} else {
log("Failed, but will not exit of failure: " + e);
}
}
return;
}
private void validateAttributes() throws BuildException {
if (null == toDir || !toDir.exists()) {
throw new BuildException("Must specify existing 'todir' directory");
}
}
}