/**
*
* Copyright (c) 2009-2016 Freedomotic team http://freedomotic.com
*
* This file is part of Freedomotic
*
* 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; either version 2, or (at your option) any later version.
*
* 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
* Freedomotic; see the file COPYING. If not, see
* <http://www.gnu.org/licenses/>.
*/
package com.freedomotic.environment.impl;
import com.freedomotic.exceptions.DataUpgradeException;
import com.freedomotic.exceptions.RepositoryException;
import com.freedomotic.model.environment.Environment;
import com.freedomotic.model.environment.Zone;
import com.freedomotic.persistence.DataUpgradeService;
import com.freedomotic.persistence.FreedomXStream;
import com.freedomotic.persistence.XmlPreprocessor;
import com.freedomotic.settings.Info;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.XStreamException;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.UUID;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
*
* @author Enrico Nicoletti
*/
class EnvironmentPersistenceImpl implements EnvironmentPersistence {
private static final Logger LOG = LoggerFactory.getLogger(EnvironmentPersistenceImpl.class.getName());
private final File directory;
private final DataUpgradeService dataUpgradeService;
@Inject
EnvironmentPersistenceImpl(@Assisted File directory, DataUpgradeService dataUpgradeService) {
this.directory = directory;
this.dataUpgradeService = dataUpgradeService;
}
/**
*
* @param file
* @return
* @throws RepositoryException
*/
public Environment deserialize(final File file) throws RepositoryException {
XStream xstream = FreedomXStream.getXstream();
//validate the object against a predefined DTD
String xml;
try {
xml = XmlPreprocessor.validate(file, Info.PATHS.PATH_CONFIG_FOLDER + "/validator/environment.dtd");
} catch (IOException ex) {
throw new RepositoryException(ex.getMessage(), ex);
}
try {
Properties dataProperties = new Properties();
String fromVersion;
try {
dataProperties.load(new FileInputStream(new File(Info.PATHS.PATH_DATA_FOLDER + "/data.properties")));
fromVersion = dataProperties.getProperty("data.version");
} catch (IOException iOException) {
// Fallback to a default version for older version without that properties file
fromVersion = "5.5.0";
}
xml = (String) dataUpgradeService.upgrade(Environment.class, xml, fromVersion);
return (Environment) xstream.fromXML(xml);
} catch (DataUpgradeException dataUpgradeException) {
throw new RepositoryException("Cannot upgrade environment file \"" + file.getAbsolutePath() + "\"", dataUpgradeException);
} catch (XStreamException e) {
throw new RepositoryException("XML parsing error. Readed XML is \n" + xml, e);
}
}
/**
* Persists an environment on filesystem using XStream as serialization
* engine (XML).
*
* @param environment
* @throws RepositoryException
*/
@Override
public void persist(Environment environment)
throws RepositoryException {
directory.mkdirs();
if (!directory.isDirectory()) {
throw new RepositoryException(directory.getAbsoluteFile() + " is not a valid environment folder. Skipped");
}
verifyFolderStructure(directory);
delete(environment);
String fileName = getEnvFilename(environment);
try {
serialize(environment, new File(directory + "/" + fileName));
} catch (IOException ex) {
throw new RepositoryException(ex);
}
}
/**
*
* @param environment
* @throws RepositoryException
*/
@Override
public void delete(Environment environment)
throws RepositoryException {
File deleteMe = new File(directory + "/" + getEnvFilename(environment));
deleteMe.delete();
}
private String getEnvFilename(Environment environment) {
String uuid = environment.getUUID();
if ((uuid == null) || uuid.isEmpty()) {
environment.setUUID(UUID.randomUUID().toString());
}
return environment.getUUID() + ".xenv";
}
/**
* Loads an environment from filesystem using XStream as serialization
* engine (XML).
*
* @return an environment object or an empty collection if no environments are found in the
* given folder
* @throws RepositoryException
*/
@Override
public Collection<Environment> loadAll() throws RepositoryException {
if (directory == null) {
throw new RepositoryException("Cannot load environments from null directory");
}
// This filter only returns env files
FileFilter envFileFilter
= new FileFilter() {
@Override
public boolean accept(File file) {
return file.isFile() && file.getName().endsWith(".xenv");
}
};
File[] files = directory.listFiles(envFileFilter);
List<Environment> environments = new ArrayList<>();
for (File file : files) {
environments.add(deserialize(file));
}
verifyFolderStructure(directory);
if (environments.isEmpty()) {
return Collections.emptyList();
}
return environments;
}
/**
*
*
* @param folder
*/
private void verifyFolderStructure(File folder) {
if (!folder.exists()) {
folder.mkdirs();
}
new File(folder + "/data").mkdir();
new File(folder + "/data/obj").mkdir();
new File(folder + "/data/rea").mkdir();
new File(folder + "/data/trg").mkdir();
new File(folder + "/data/cmd").mkdir();
new File(folder + "/data/resources").mkdir();
}
/**
*
*
* @param env
* @param file
* @throws IOException
*/
private void serialize(Environment env, File file) throws IOException {
for (Zone zone : env.getZones()) {
zone.setObjects(null);
}
LOG.info("Serializing environment to \"{}\"", file);
FreedomXStream.toXML(env, file);
LOG.info("Application environment \"{}\" successfully serialized", env.getName());
}
}