/**
* Copyright (c) 2009--2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.manager.configuration;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.validator.ValidatorError;
import com.redhat.rhn.common.validator.ValidatorException;
import com.redhat.rhn.common.validator.ValidatorResult;
import com.redhat.rhn.domain.config.ConfigChannel;
import com.redhat.rhn.domain.config.ConfigContent;
import com.redhat.rhn.domain.config.ConfigFile;
import com.redhat.rhn.domain.config.ConfigFileState;
import com.redhat.rhn.domain.config.ConfigFileType;
import com.redhat.rhn.domain.config.ConfigRevision;
import com.redhat.rhn.domain.config.ConfigurationFactory;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.action.configuration.ConfigFileForm;
import com.redhat.rhn.manager.configuration.file.ConfigFileData;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
/**
* ConfigFileCreationHelper
* @version $Rev$
*/
public class ConfigFileBuilder {
private static final ConfigFileBuilder HELPER =
new ConfigFileBuilder();
private ConfigFileBuilder() {
}
/**
* @return an instance of this class
*/
public static ConfigFileBuilder getInstance() {
return HELPER;
}
/**
* Validates the passed in channel using the info provided
* @param cff the ConfigFileForm associated to the request
* @param user the logged in user
* @param channel the config channel.
* @return returns a ValidatorResult
*/
private void validateForCreate(ConfigFileData cff,
User user, ConfigChannel channel) throws ValidatorException {
cff.validatePath();
// File exists? Report and bolt
String path = cff.getPath();
if (fileExists(user, path, channel)) {
ValidatorResult result = new ValidatorResult();
result.addError(new ValidatorError("config.error.file-exists", path));
throw new ValidatorException(result);
}
cff.validate(true);
}
/**
*
* @param user the logged in user
* @param form the config file form
* @param cc the config channel
* @return True if file exists false other wise
*/
private boolean fileExists(
User user, String path, ConfigChannel cc) {
ConfigFile file = null;
if (path != null && path.trim().length() > 0) {
file = ConfigurationManager.getInstance().
lookupConfigFile(user, cc.getId(), path);
}
return (file != null);
}
/**
* Creates a new config file using the information provided
* in the config file form.
* @param cff the config file from holding input data
* @param user the logged in user.
* @param channel the channel to create file in.
* @return the newest revision of the created config file..
* @throws IOException in the case of issues with content stream reading.
* @throws ValidatorException in the case of invalid data passed in.
*/
public ConfigRevision create(ConfigFileData cff,
User user, ConfigChannel channel)
throws IOException, ValidatorException {
validateForCreate(cff, user, channel);
// Yay! We actually might be able to create this file!
ConfigFile cf = channel.createConfigFile(ConfigFileState.normal(),
cff.getPath());
return makeNewRevision(user, cff, cf, true);
}
/**
* Creates a new New config revision of a config file using the passed in data.
* @param user the logged in user
* @param form the config file form
* @param cf the the config file to populate and commit
* @return the newly createed config revision.
* @throws IOException in the case of error in reading content stream.
*/
private ConfigRevision makeNewRevision(User user, ConfigFileData form,
ConfigFile cf, boolean onCreate) {
ConfigurationManager manager = ConfigurationManager.getInstance();
ConfigRevision prevRevision = cf.getLatestConfigRevision();
ConfigRevision revision;
String delimStart = form.getMacroStart();
String delimEnd = form.getMacroEnd();
if (onCreate) {
revision = ConfigurationFactory.newConfigRevision();
ConfigContent content = null;
if (ConfigFileType.file().equals(form.getType())) {
if (form.isBinary()) {
// if not given, use the default value
if (delimStart == null) {
delimStart = ConfigFileForm.DEFAULT_CONFIG_DELIM_START;
}
if (delimEnd == null) {
delimEnd = ConfigFileForm.DEFAULT_CONFIG_DELIM_END;
}
}
}
}
else {
if ((prevRevision != null) &&
form.matchesRevision(prevRevision)) {
return prevRevision;
}
revision = prevRevision.copy();
if (StringUtils.isEmpty(delimStart)) {
delimStart = prevRevision.getConfigContent().getDelimStart();
}
if (StringUtils.isEmpty(delimEnd)) {
delimEnd = prevRevision.getConfigContent().getDelimStart();
}
if (!StringUtils.isEmpty(form.getRevNumber())) {
revision.setRevision(Long.parseLong(form.getRevNumber()));
}
else {
revision.setRevision(ConfigurationFactory.getNextRevisionForFile(cf));
}
}
revision.setConfigContent(
ConfigurationFactory.createNewContentFromStream(
form.getContentStream(), form.getContentSize(),
form.isBinary(), delimStart, delimEnd));
revision.setChangedById(user.getId());
revision.setConfigInfo(form.extractInfo());
revision.setConfigFileType(form.getType());
revision.setConfigFile(cf);
// Committing the revision commits the file for us (which commits the
// Channel, so everybody's pointers get updated...)
return ConfigurationFactory.commit(revision);
}
/**
* Updates a config file
* depending on the data in the given configFileForm..
* @param form the ConfigFileData form containing the input data
* @param user the logged in user.
* @param file the config file to update.
* @return the create revision of the file.
* @throws ValidatorException in the case of invalid data.
*/
public ConfigRevision update(ConfigFileData form,
User user, ConfigFile file)
throws ValidatorException {
form.validatePath();
ValidatorResult result;
ConfigRevision latestRevision = file.getLatestConfigRevision();
if (!form.getType().equals(latestRevision.getConfigFileType())) {
LocalizationService ls = LocalizationService.getInstance();
String fromType = ls.getMessage(latestRevision.
getConfigFileType().getMessageKey());
String toType = ls.getMessage(form.getType().getMessageKey());
ValidatorException.raiseException("error.config-cannot-change-type",
form.getPath(), fromType, toType);
}
try {
if (!StringUtils.isBlank(form.getRevNumber())) {
Long l = Long.parseLong(form.getRevNumber());
if (l.longValue() <= latestRevision.getRevision()) {
result = new ValidatorResult();
result.addError(new ValidatorError("error.config.revnum.too-old",
form.getPath()));
throw new ValidatorException(result);
}
}
else {
form.setRevNumber(String.valueOf(
latestRevision.getRevision() + 1));
}
}
catch (NumberFormatException nfe) {
result = new ValidatorResult();
result.addError(new ValidatorError("error.config.revnum.invalid",
form.getPath()));
throw new ValidatorException(result);
}
form.validate(false);
return makeNewRevision(user, form, file, false);
}
/**
* Creates Or Updates a config file
* depending on the data in the given configFileForm..
* i.e. if a file with the given path exists, it updates the
* file with that path. Else it creates a new file of the path..
* @param form the config file form with the input data
* @param user the logged in user.
* @param cc the config channel of the file
* @return the create revision of the file.
* @throws IOException in the case of issues due to parsing of contents.
* @throws ValidatorException in the case of invalid data.
*/
public ConfigRevision createOrUpdate(ConfigFileData form,
User user, ConfigChannel cc)
throws IOException, ValidatorException {
String path = form.getPath();
ConfigurationManager manager = ConfigurationManager.getInstance();
ConfigFile file = manager.lookupConfigFile(user, cc.getId(), path);
if (file == null) {
return create(form, user, cc);
}
return update(form, user, file);
}
}