From 66e342c82384d5225fe3565466ca2f261f71c400 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 8 Sep 2010 17:14:12 +0200 Subject: [PATCH] added package sonia.scm.io --- .../java/sonia/scm/io/AbstractReader.java | 113 ++++++++++++++ .../java/sonia/scm/io/AbstractWriter.java | 78 ++++++++++ .../src/main/java/sonia/scm/io/Command.java | 30 ++++ .../main/java/sonia/scm/io/CommandResult.java | 40 +++++ .../java/sonia/scm/io/ExtendedCommand.java | 96 ++++++++++++ .../java/sonia/scm/io/INIConfiguration.java | 86 +++++++++++ .../sonia/scm/io/INIConfigurationReader.java | 92 +++++++++++ .../sonia/scm/io/INIConfigurationWriter.java | 45 ++++++ .../main/java/sonia/scm/io/INISection.java | 142 +++++++++++++++++ .../scm/io/ProcessInterruptScheduler.java | 48 ++++++ .../main/java/sonia/scm/io/SimpleCommand.java | 143 ++++++++++++++++++ .../sonia/scm/io/SimpleCommandResult.java | 75 +++++++++ .../src/main/java/sonia/scm/util/Util.java | 33 ++++ 13 files changed, 1021 insertions(+) create mode 100644 scm-core/src/main/java/sonia/scm/io/AbstractReader.java create mode 100644 scm-core/src/main/java/sonia/scm/io/AbstractWriter.java create mode 100644 scm-core/src/main/java/sonia/scm/io/Command.java create mode 100644 scm-core/src/main/java/sonia/scm/io/CommandResult.java create mode 100644 scm-core/src/main/java/sonia/scm/io/ExtendedCommand.java create mode 100644 scm-core/src/main/java/sonia/scm/io/INIConfiguration.java create mode 100644 scm-core/src/main/java/sonia/scm/io/INIConfigurationReader.java create mode 100644 scm-core/src/main/java/sonia/scm/io/INIConfigurationWriter.java create mode 100644 scm-core/src/main/java/sonia/scm/io/INISection.java create mode 100644 scm-core/src/main/java/sonia/scm/io/ProcessInterruptScheduler.java create mode 100644 scm-core/src/main/java/sonia/scm/io/SimpleCommand.java create mode 100644 scm-core/src/main/java/sonia/scm/io/SimpleCommandResult.java diff --git a/scm-core/src/main/java/sonia/scm/io/AbstractReader.java b/scm-core/src/main/java/sonia/scm/io/AbstractReader.java new file mode 100644 index 0000000000..b71530af70 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/AbstractReader.java @@ -0,0 +1,113 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * + * @author Sebastian Sdorra + * + * @param + */ +public abstract class AbstractReader +{ + + /** + * Method description + * + * + * @param input + * + * @return + * + * @throws IOException + */ + public abstract T read(InputStream input) throws IOException; + + /** + * Method description + * + * + * @param data + * + * @return + * + * @throws IOException + */ + public T read(byte[] data) throws IOException + { + T result = null; + InputStream input = null; + + try + { + input = new ByteArrayInputStream(data); + result = read(input); + } + finally + { + Util.close(input); + } + + return result; + } + + /** + * Method description + * + * + * @param path + * + * @return + * + * @throws IOException + */ + public T read(String path) throws IOException + { + return read(new File(path)); + } + + /** + * Method description + * + * + * @param file + * + * @return + * + * @throws IOException + */ + public T read(File file) throws IOException + { + T result = null; + InputStream input = null; + + try + { + input = new FileInputStream(file); + result = read(input); + } + finally + { + Util.close(input); + } + + return result; + } +} diff --git a/scm-core/src/main/java/sonia/scm/io/AbstractWriter.java b/scm-core/src/main/java/sonia/scm/io/AbstractWriter.java new file mode 100644 index 0000000000..6198731a2a --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/AbstractWriter.java @@ -0,0 +1,78 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +/** + * + * @author Sebastian Sdorra + * + * @param + */ +public abstract class AbstractWriter +{ + + /** + * Method description + * + * + * @param object + * @param output + * + * @throws IOException + */ + public abstract void write(T object, OutputStream output) throws IOException; + + /** + * Method description + * + * + * @param object + * @param file + * + * @throws IOException + */ + public void write(T object, File file) throws IOException + { + OutputStream output = null; + + try + { + output = new FileOutputStream(file); + write(object, output); + } + finally + { + Util.close(output); + } + } + + /** + * Method description + * + * + * @param object + * @param path + * + * @throws IOException + */ + public void write(T object, String path) throws IOException + { + write(object, new File(path)); + } +} diff --git a/scm-core/src/main/java/sonia/scm/io/Command.java b/scm-core/src/main/java/sonia/scm/io/Command.java new file mode 100644 index 0000000000..9063fbd33c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/Command.java @@ -0,0 +1,30 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +/** + * + * @author Sebastian Sdorra + */ +public interface Command +{ + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + public CommandResult execute() throws IOException; +} diff --git a/scm-core/src/main/java/sonia/scm/io/CommandResult.java b/scm-core/src/main/java/sonia/scm/io/CommandResult.java new file mode 100644 index 0000000000..7284978c02 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/CommandResult.java @@ -0,0 +1,40 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +/** + * + * @author Sebastian Sdorra + */ +public interface CommandResult +{ + + /** + * Method description + * + * + * @return + */ + public String getOutput(); + + /** + * Method description + * + * + * @return + */ + public int getReturnCode(); + + /** + * Method description + * + * + * @return + */ + public boolean isSuccessfull(); +} diff --git a/scm-core/src/main/java/sonia/scm/io/ExtendedCommand.java b/scm-core/src/main/java/sonia/scm/io/ExtendedCommand.java new file mode 100644 index 0000000000..6d0dd21f3c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/ExtendedCommand.java @@ -0,0 +1,96 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; + +import java.util.Timer; + +/** + * + * @author Sebastian Sdorra + */ +public class ExtendedCommand extends SimpleCommand +{ + + /** + * Constructs ... + * + * + * @param command + */ + public ExtendedCommand(String... command) + { + super(command); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + @Override + public SimpleCommandResult execute() throws IOException + { + SimpleCommandResult result = null; + Process process = createProcess(); + Timer timer = new Timer(); + ProcessInterruptScheduler pis = null; + + try + { + pis = new ProcessInterruptScheduler(process); + timer.schedule(pis, timeout); + result = getResult(process); + } + finally + { + timer.cancel(); + } + + return result; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public long getTimeout() + { + return timeout; + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param timeout + */ + public void setTimeout(long timeout) + { + this.timeout = timeout; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private long timeout = 30000; +} diff --git a/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java b/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java new file mode 100644 index 0000000000..91256e208c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/INIConfiguration.java @@ -0,0 +1,86 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * + * @author Sebastian Sdorra + */ +public class INIConfiguration +{ + + /** + * Constructs ... + * + */ + public INIConfiguration() + { + this.sectionMap = new LinkedHashMap(); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param section + */ + public void addSection(INISection section) + { + sectionMap.put(section.getName(), section); + } + + /** + * Method description + * + * + * @param name + */ + public void removeSection(String name) + { + sectionMap.remove(name); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param name + * + * @return + */ + public INISection getSection(String name) + { + return sectionMap.get(name); + } + + /** + * Method description + * + * + * @return + */ + public Collection getSections() + { + return sectionMap.values(); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Map sectionMap; +} diff --git a/scm-core/src/main/java/sonia/scm/io/INIConfigurationReader.java b/scm-core/src/main/java/sonia/scm/io/INIConfigurationReader.java new file mode 100644 index 0000000000..b6d36bbdc3 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/INIConfigurationReader.java @@ -0,0 +1,92 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Sebastian Sdorra + */ +public class INIConfigurationReader extends AbstractReader +{ + + /** Field description */ + private static final Pattern sectionPattern = + Pattern.compile("\\[([^\\]]+)\\]"); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param input + * + * @return + * + * @throws IOException + */ + @Override + public INIConfiguration read(InputStream input) throws IOException + { + INIConfiguration configuration = new INIConfiguration(); + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + INISection section = null; + String line = reader.readLine(); + + while (line != null) + { + line = line.trim(); + + Matcher sectionMatcher = sectionPattern.matcher(line); + + if (sectionMatcher.matches()) + { + String name = sectionMatcher.group(1); + + if (section != null) + { + configuration.addSection(section); + } + + section = new INISection(name); + } + else if ((section != null) &&!line.startsWith(";") + &&!line.startsWith("#")) + { + int index = line.indexOf("="); + + if (index > 0) + { + String key = line.substring(0, index).trim(); + String value = line.substring(index + 1, line.length()).trim(); + + section.setParameter(key, value); + } + } + + line = reader.readLine(); + } + + if (section != null) + { + configuration.addSection(section); + } + + return configuration; + } +} diff --git a/scm-core/src/main/java/sonia/scm/io/INIConfigurationWriter.java b/scm-core/src/main/java/sonia/scm/io/INIConfigurationWriter.java new file mode 100644 index 0000000000..d380dcaa93 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/INIConfigurationWriter.java @@ -0,0 +1,45 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintWriter; + +/** + * + * @author Sebastian Sdorra + */ +public class INIConfigurationWriter extends AbstractWriter +{ + + /** + * Method description + * + * + * @param object + * @param output + * + * @throws IOException + */ + @Override + public void write(INIConfiguration object, OutputStream output) + throws IOException + { + PrintWriter writer = new PrintWriter(output); + + for (INISection section : object.getSections()) + { + writer.println(section.toString()); + } + + writer.flush(); + } +} diff --git a/scm-core/src/main/java/sonia/scm/io/INISection.java b/scm-core/src/main/java/sonia/scm/io/INISection.java new file mode 100644 index 0000000000..2a76ceb31e --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/INISection.java @@ -0,0 +1,142 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * + * @author Sebastian Sdorra + */ +public class INISection +{ + + /** + * Constructs ... + * + * + * @param name + */ + public INISection(String name) + { + this.name = name; + this.parameters = new LinkedHashMap(); + } + + /** + * Constructs ... + * + * + * @param name + * @param parameters + */ + public INISection(String name, Map parameters) + { + this.name = name; + this.parameters = parameters; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param key + */ + public void removeParameter(String key) + { + parameters.put(key, name); + } + + /** + * Method description + * + * + * @return + */ + @Override + public String toString() + { + String s = System.getProperty("line.separator"); + StringBuilder out = new StringBuilder(); + + out.append("[").append(name).append("]").append(s); + + for (Map.Entry entry : parameters.entrySet()) + { + out.append(entry.getKey()).append(" = ").append(entry.getValue()); + out.append(s); + } + + return out.toString(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public String getName() + { + return name; + } + + /** + * Method description + * + * + * @param key + * + * @return + */ + public String getParameter(String key) + { + return parameters.get(key); + } + + /** + * Method description + * + * + * @return + */ + public Collection getParameterKeys() + { + return parameters.keySet(); + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param key + * @param value + */ + public void setParameter(String key, String value) + { + parameters.put(key, value); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String name; + + /** Field description */ + private Map parameters; +} diff --git a/scm-core/src/main/java/sonia/scm/io/ProcessInterruptScheduler.java b/scm-core/src/main/java/sonia/scm/io/ProcessInterruptScheduler.java new file mode 100644 index 0000000000..e6cb991cdf --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/ProcessInterruptScheduler.java @@ -0,0 +1,48 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.TimerTask; + +/** + * + * @author Sebastian Sdorra + */ +public class ProcessInterruptScheduler extends TimerTask +{ + + /** + * Constructs ... + * + * + * @param process + */ + public ProcessInterruptScheduler(Process process) + { + this.process = process; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + @Override + public void run() + { + process.destroy(); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private Process process; +} diff --git a/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java b/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java new file mode 100644 index 0000000000..42c0a8230d --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/SimpleCommand.java @@ -0,0 +1,143 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.util.Util; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + * @author Sebastian Sdorra + */ +public class SimpleCommand implements Command +{ + + /** Field description */ + private static final Logger logger = + Logger.getLogger(SimpleCommand.class.getName()); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param command + */ + public SimpleCommand(String... command) + { + this.command = command; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + @Override + public SimpleCommandResult execute() throws IOException + { + Process process = createProcess(); + + return getResult(process); + } + + /** + * Method description + * + * + * @return + * + * @throws IOException + */ + protected Process createProcess() throws IOException + { + ProcessBuilder processBuilder = new ProcessBuilder(command); + + processBuilder.redirectErrorStream(true); + + return processBuilder.start(); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param process + * + * @return + * + * @throws IOException + */ + protected SimpleCommandResult getResult(Process process) throws IOException + { + SimpleCommandResult result = null; + InputStream input = null; + + try + { + String s = System.getProperty("line.separator"); + StringBuilder content = new StringBuilder(); + + input = process.getInputStream(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(input)); + String line = reader.readLine(); + + while (line != null) + { + content.append(line); + line = reader.readLine(); + + if (line != null) + { + content.append(s); + } + } + + int returnCode = process.waitFor(); + + result = new SimpleCommandResult(content.toString(), returnCode); + } + catch (InterruptedException ex) + { + logger.log(Level.SEVERE, null, ex); + + throw new IOException(ex.getMessage()); + } + finally + { + Util.close(input); + } + + return result; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String[] command; +} diff --git a/scm-core/src/main/java/sonia/scm/io/SimpleCommandResult.java b/scm-core/src/main/java/sonia/scm/io/SimpleCommandResult.java new file mode 100644 index 0000000000..fd90504daf --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/io/SimpleCommandResult.java @@ -0,0 +1,75 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + + + +package sonia.scm.io; + +/** + * + * @author Sebastian Sdorra + */ +public class SimpleCommandResult implements CommandResult +{ + + /** + * Constructs ... + * + * + * @param output + * @param returnCode + */ + public SimpleCommandResult(String output, int returnCode) + { + this.output = output; + this.returnCode = returnCode; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public String getOutput() + { + return output; + } + + /** + * Method description + * + * + * @return + */ + @Override + public int getReturnCode() + { + return returnCode; + } + + /** + * Method description + * + * + * @return + */ + @Override + public boolean isSuccessfull() + { + return returnCode == 0; + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String output; + + /** Field description */ + private int returnCode; +} diff --git a/scm-core/src/main/java/sonia/scm/util/Util.java b/scm-core/src/main/java/sonia/scm/util/Util.java index 0074c85374..41251577c4 100644 --- a/scm-core/src/main/java/sonia/scm/util/Util.java +++ b/scm-core/src/main/java/sonia/scm/util/Util.java @@ -9,7 +9,12 @@ package sonia.scm.util; //~--- JDK imports ------------------------------------------------------------ +import java.io.Closeable; +import java.io.IOException; + import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; /** * @@ -18,6 +23,34 @@ import java.util.Collection; public class Util { + /** Field description */ + private static final Logger logger = Logger.getLogger(Util.class.getName()); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param closeable + */ + public static void close(Closeable closeable) + { + if (closeable != null) + { + try + { + closeable.close(); + } + catch (IOException ex) + { + logger.log(Level.SEVERE, null, ex); + } + } + } + + //~--- get methods ---------------------------------------------------------- + /** * Method description *