/*
* Copyright 2014 Simon FLandergan
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.sflan.file.symlinker;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.concurrent.TimeUnit;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import de.sflan.file.symlinker.config.Config;
import de.sflan.file.symlinker.config.SyncPair;
import de.sflan.file.symlinker.schedule.FolderWatcher;
/**
* Main class reading configuration and starting the {@link FolderWatcher}
* Automatically stops, when a 'shutdown.do' file is placed in the home directory
* @author simon.flandergan
*
*/
public class SymLinker {
private static Logger logger = Logger.getLogger(SymLinker.class.getSimpleName());
/**
* @param args
*/
public static void main(String[] args) {
try {
LogManager.getLogManager().readConfiguration(
SymLinker.class.getResourceAsStream("/logging.properties"));
} catch (SecurityException | IOException e1) {
throw new IllegalStateException("Application is missing logging properties");
}
if (args.length != 1) {
throw new IllegalArgumentException(
"Expecting exactly one argument (config file)");
}
Path configPath = Paths.get(args[0]);
if (!Files.exists(configPath)) {
throw new IllegalArgumentException(MessageFormat.format(
"Config file {0} does not exist", configPath));
}
logger.info("Reading configuration ...");
Config config = readConfig(configPath);
logger.info("Validating configuration ...");
validateConfig(config);
FolderWatcher watcher = new FolderWatcher(config);
/*
* start the watcher
*/
watcher.start();
/*
* run as long we have no shutdown file
*/
try {
while (!shutdownFileExists()) {
try {
Thread.sleep(TimeUnit.SECONDS.toMillis(20));
} catch (InterruptedException e) {
/*
* ignore and continue
*/
}
}
} finally {
logger.info("Shutting down");
/*
* stop the watcher and end
*/
watcher.stop();
logger.info("Done");
}
}
private static Config readConfig(Path config) {
StreamSource source = null;
try {
JAXBContext context = JAXBContext.newInstance(Config.class);
/*
* create validation schema
*/
SchemaFactory factory = SchemaFactory
.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
source = new StreamSource(
SymLinker.class.getResourceAsStream("/xsd/config.xsd"));
Schema schema = factory.newSchema(source);
Unmarshaller unmarshaller = context.createUnmarshaller();
unmarshaller.setSchema(schema);
return (Config) unmarshaller.unmarshal(new StreamSource(config.toFile()), Config.class).getValue();
} catch (JAXBException e) {
throw new IllegalArgumentException("Error parsing config", e);
} catch (SAXException e) {
throw new IllegalArgumentException("Validation issue", e);
}
}
private static boolean shutdownFileExists() {
File file = new File("shutdown.do");
boolean result = file.exists();
if (result) {
file.delete();
}
return result;
}
private static void validateConfig(Config config) {
/*
* check if all folders exist
*/
for (SyncPair pair : config.getSyncPair()){
Path path = Paths.get(pair.getSource());
if (!Files.exists(path)){
throw new RuntimeException(MessageFormat.format(
"Error in configuration. Source folder ''{0}'' does not exist", path));
}
path = Paths.get(pair.getTarget());
if (!Files.exists(path)){
throw new RuntimeException(MessageFormat.format(
"Error in configuration. Target folder ''{0}'' does not exist", path));
}
}
}
}