BuildFile and FS modules implementation [commit 2]
This commit is contained in:
@@ -19,4 +19,25 @@
|
||||
<version>${global.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>${groupId}.${artifactId}-${version}</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<version>2.3.5</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-Name>Arcadex System: ${name} ${version}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${groupId}.${artifactId}</Bundle-SymbolicName>
|
||||
<Bundle-Activator>eu.arcadex.system.build_sequence.Activator</Bundle-Activator>
|
||||
<Export-Package>eu.arcadex.system.build_sequence.api</Export-Package>
|
||||
<Import-Package>*</Import-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,44 @@
|
||||
package eu.arcadex.system.build_sequence;
|
||||
|
||||
import eu.arcadex.system.build_sequence.api.IBuildFileFactory;
|
||||
import eu.arcadex.system.build_sequence.implementation.BuildFileFactory;
|
||||
import eu.arcadex.system.file_system.api.IFileSystem;
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceRegistration;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
|
||||
/**
|
||||
* @author Daniil on 08.04.16.
|
||||
*/
|
||||
public class Activator implements BundleActivator {
|
||||
private ServiceTracker<?, IFileSystem> fileSystemServiceTracker;
|
||||
private ServiceRegistration<?> service;
|
||||
|
||||
@Override
|
||||
public void start(BundleContext bundleContext) throws Exception {
|
||||
fileSystemServiceTracker = new ServiceTracker(bundleContext, IFileSystem.class.getName(), null);
|
||||
fileSystemServiceTracker.open();
|
||||
|
||||
service = bundleContext.registerService(IBuildFileFactory.class.getName(), new BuildFileFactory(this), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(BundleContext bundleContext) throws Exception {
|
||||
service.unregister();
|
||||
}
|
||||
|
||||
public IFileSystem getFileSystem() {
|
||||
IFileSystem db = null;
|
||||
try {
|
||||
db = fileSystemServiceTracker.waitForService(5000);
|
||||
} catch (InterruptedException ignore) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
if (db == null) {
|
||||
throw new RuntimeException("Service \"IFileSystem\" not found!");
|
||||
}
|
||||
return db;
|
||||
}
|
||||
}
|
||||
250
build_files/src/main/java/eu/arcadex/system/build_sequence/CommandLine.java
Executable file
250
build_files/src/main/java/eu/arcadex/system/build_sequence/CommandLine.java
Executable file
@@ -0,0 +1,250 @@
|
||||
package eu.arcadex.system.build_sequence;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Commandline objects help handling command lines specifying processes to
|
||||
* execute.
|
||||
* <p>
|
||||
* The class can be used to define a command line as nested elements or as a
|
||||
* helper to define a command line by an application.
|
||||
* <p>
|
||||
* <code>
|
||||
* <someelement><br>
|
||||
* <acommandline executable="/executable/to/run"><br>
|
||||
* <argument value="argument 1" /><br>
|
||||
* <argument line="argument_1 argument_2 argument_3" /><br>
|
||||
* <argument value="argument 4" /><br>
|
||||
* </acommandline><br>
|
||||
* </someelement><br>
|
||||
* </code>
|
||||
* The element <code>someelement</code> must provide a method
|
||||
* <code>createAcommandline</code> which returns an instance of this class.
|
||||
*/
|
||||
public class CommandLine implements Cloneable {
|
||||
/** win9x uses a (shudder) bat file (antRun.bat) for executing commands */
|
||||
|
||||
/**
|
||||
* The arguments of the command
|
||||
*/
|
||||
private List<Argument> arguments = new ArrayList<Argument>();
|
||||
|
||||
/**
|
||||
* the program to execute
|
||||
*/
|
||||
private String executable = null;
|
||||
|
||||
/**
|
||||
* Put quotes around the given String if necessary.
|
||||
* <p>
|
||||
* <p>If the argument doesn't include spaces or quotes, return it
|
||||
* as is. If it contains double quotes, use single quotes - else
|
||||
* surround the argument by double quotes.</p>
|
||||
*
|
||||
* @param argument the argument to quote if necessary.
|
||||
* @return the quoted argument.
|
||||
*/
|
||||
public static String quoteArgument(String argument) {
|
||||
if (argument.contains("\"")) {
|
||||
if (argument.contains("\'")) {
|
||||
throw new RuntimeException("Can\'t handle single and double"
|
||||
+ " quotes in same argument");
|
||||
} else {
|
||||
return '\'' + argument + '\'';
|
||||
}
|
||||
} else if (argument.contains("\'")
|
||||
|| argument.contains(" ")) {
|
||||
return '\"' + argument + '\"';
|
||||
} else {
|
||||
return argument;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Quote the parts of the given array in way that makes them
|
||||
* usable as command line arguments.
|
||||
*
|
||||
* @param line the list of arguments to quote.
|
||||
* @return empty string for null or no command, else every argument split
|
||||
* by spaces and quoted by quoting rules.
|
||||
*/
|
||||
public static String toString(String[] line) {
|
||||
// empty path return empty string
|
||||
if (line == null || line.length == 0) {
|
||||
return "";
|
||||
}
|
||||
// path containing one or more elements
|
||||
final StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < line.length; i++) {
|
||||
if (i > 0) {
|
||||
result.append(' ');
|
||||
}
|
||||
result.append(quoteArgument(line[i]));
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Crack a command line.
|
||||
*
|
||||
* @param toProcess the command line to process.
|
||||
* @return the command line broken into strings.
|
||||
* An empty or null toProcess parameter results in a zero sized array.
|
||||
*/
|
||||
public static String[] translateCommandline(String toProcess) {
|
||||
if (toProcess == null || toProcess.length() == 0) {
|
||||
//no command? no string
|
||||
return new String[0];
|
||||
}
|
||||
// parse with a simple finite state machine
|
||||
|
||||
final int normal = 0;
|
||||
final int inQuote = 1;
|
||||
final int inDoubleQuote = 2;
|
||||
int state = normal;
|
||||
final StringTokenizer tok = new StringTokenizer(toProcess, "\"\' ", true);
|
||||
final ArrayList<String> result = new ArrayList<>();
|
||||
final StringBuilder current = new StringBuilder();
|
||||
boolean lastTokenHasBeenQuoted = false;
|
||||
|
||||
while (tok.hasMoreTokens()) {
|
||||
String nextTok = tok.nextToken();
|
||||
switch (state) {
|
||||
case inQuote:
|
||||
if ("\'".equals(nextTok)) {
|
||||
lastTokenHasBeenQuoted = true;
|
||||
state = normal;
|
||||
} else {
|
||||
current.append(nextTok);
|
||||
}
|
||||
break;
|
||||
case inDoubleQuote:
|
||||
if ("\"".equals(nextTok)) {
|
||||
lastTokenHasBeenQuoted = true;
|
||||
state = normal;
|
||||
} else {
|
||||
current.append(nextTok);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if ("\'".equals(nextTok)) {
|
||||
state = inQuote;
|
||||
} else if ("\"".equals(nextTok)) {
|
||||
state = inDoubleQuote;
|
||||
} else if (" ".equals(nextTok)) {
|
||||
if (lastTokenHasBeenQuoted || current.length() != 0) {
|
||||
result.add(current.toString());
|
||||
current.setLength(0);
|
||||
}
|
||||
} else {
|
||||
current.append(nextTok);
|
||||
}
|
||||
lastTokenHasBeenQuoted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastTokenHasBeenQuoted || current.length() != 0) {
|
||||
result.add(current.toString());
|
||||
}
|
||||
if (state == inQuote || state == inDoubleQuote) {
|
||||
throw new RuntimeException("unbalanced quotes in " + toProcess);
|
||||
}
|
||||
return result.toArray(new String[result.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the executable and all defined arguments.
|
||||
*
|
||||
* @return the commandline as an array of strings.
|
||||
*/
|
||||
public String[] getCommandline() {
|
||||
final List<String> commands = new LinkedList<String>();
|
||||
addCommandToList(commands.listIterator());
|
||||
return commands.toArray(new String[commands.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the entire command, including (optional) executable to a list.
|
||||
*
|
||||
* @param list the list to add to.
|
||||
* @since Ant 1.6
|
||||
*/
|
||||
public void addCommandToList(ListIterator<String> list) {
|
||||
if (executable != null) {
|
||||
list.add(executable);
|
||||
}
|
||||
addArgumentsToList(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append all the arguments to the tail of a supplied list.
|
||||
*
|
||||
* @param list the list of arguments.
|
||||
* @since Ant 1.6
|
||||
*/
|
||||
public void addArgumentsToList(ListIterator<String> list) {
|
||||
for (Argument arg : arguments) {
|
||||
String[] s = arg.getParts();
|
||||
if (s != null) {
|
||||
for (String value : s) {
|
||||
list.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the command line as a string.
|
||||
*
|
||||
* @return the command line.
|
||||
*/
|
||||
public String toString() {
|
||||
return toString(getCommandline());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a deep clone of the contained object.
|
||||
*
|
||||
* @return a clone of the contained object
|
||||
*/
|
||||
public Object clone() {
|
||||
try {
|
||||
CommandLine c = (CommandLine) super.clone();
|
||||
c.arguments = new ArrayList<>(arguments);
|
||||
return c;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used for nested xml command line definitions.
|
||||
*/
|
||||
public static class Argument {
|
||||
|
||||
private String[] parts;
|
||||
|
||||
private String prefix = "";
|
||||
private String suffix = "";
|
||||
|
||||
|
||||
/**
|
||||
* Return the constituent parts of this Argument.
|
||||
*
|
||||
* @return an array of strings.
|
||||
*/
|
||||
public String[] getParts() {
|
||||
if (parts == null || parts.length == 0
|
||||
|| (prefix.length() == 0 && suffix.length() == 0)) {
|
||||
return parts;
|
||||
}
|
||||
String[] fullParts = new String[parts.length];
|
||||
for (int i = 0; i < fullParts.length; ++i) {
|
||||
fullParts[i] = prefix + parts[i] + suffix;
|
||||
}
|
||||
return fullParts;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package eu.arcadex.system.build_sequence.api;
|
||||
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public enum IBuildCommand {
|
||||
INH(false, 1), // Disable or enable Build file inheritance
|
||||
MKDIRS(true, 1), //
|
||||
COPY(true, 2),
|
||||
LNK(true, 2),
|
||||
UNZIP(true, 2);
|
||||
|
||||
|
||||
// Флаг, указывающий на то, стоит ли рассматривать
|
||||
// команду как призыв к действию
|
||||
private boolean execute = false;
|
||||
private int argumentCount = 0;
|
||||
|
||||
IBuildCommand(boolean execute, int argumentCount) {
|
||||
this.execute = execute;
|
||||
this.argumentCount = argumentCount;
|
||||
}
|
||||
|
||||
public boolean isExecute() {
|
||||
return execute;
|
||||
}
|
||||
|
||||
public int getArgumentCount() {
|
||||
return argumentCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package eu.arcadex.system.build_sequence.api;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public interface IBuildEnvironment {
|
||||
void add(String from, String to);
|
||||
|
||||
String process(String message);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package eu.arcadex.system.build_sequence.api;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public interface IBuildFile {
|
||||
LinkedList<IBuildStep> getCommands();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package eu.arcadex.system.build_sequence.api;
|
||||
|
||||
import eu.arcadex.system.build_sequence.implementation.MalformedBuildFileException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Daniil on 08.04.16.
|
||||
*/
|
||||
public interface IBuildFileFactory {
|
||||
IBuildFile getFromFile(File file) throws IOException, MalformedBuildFileException;
|
||||
|
||||
IBuildFile getFromStringList(List<String> list) throws MalformedBuildFileException;
|
||||
|
||||
IBuildEnvironment createEnvironment();
|
||||
|
||||
IBuildSequence createSequence();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package eu.arcadex.system.build_sequence.api;
|
||||
|
||||
/**
|
||||
* @author Daniil on 08.04.16.
|
||||
*/
|
||||
public interface IBuildSequence {
|
||||
void setInheritance(boolean inheritance);
|
||||
|
||||
void add(IBuildStep step);
|
||||
|
||||
void include(IBuildFile buildFile);
|
||||
|
||||
void execute(IBuildEnvironment environment) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package eu.arcadex.system.build_sequence.api;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public interface IBuildStep {
|
||||
void execute(IBuildEnvironment impl) throws Exception;
|
||||
|
||||
IBuildCommand getCommand();
|
||||
|
||||
String[] getArgs();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package eu.arcadex.system.build_sequence.implementation;
|
||||
|
||||
import eu.arcadex.system.build_sequence.api.IBuildEnvironment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public class BuildEnvironment implements IBuildEnvironment {
|
||||
private Map<String, String> replaces = new HashMap<>();
|
||||
|
||||
public void add(String from, String to) {
|
||||
replaces.put(from, to);
|
||||
}
|
||||
|
||||
public String process(String message) {
|
||||
for (Map.Entry<String, String> entry : replaces.entrySet()) {
|
||||
message = message.replaceAll("%" + entry.getKey() + "%", entry.getValue());
|
||||
}
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package eu.arcadex.system.build_sequence.implementation;
|
||||
|
||||
import eu.arcadex.system.build_sequence.Activator;
|
||||
import eu.arcadex.system.build_sequence.api.*;
|
||||
import eu.arcadex.system.file_system.api.IFileSystem;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Daniil on 08.04.16.
|
||||
*/
|
||||
public class BuildFileFactory implements IBuildFileFactory {
|
||||
private Activator parent;
|
||||
|
||||
public BuildFileFactory(Activator parent) {
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public IBuildFile getFromFile(File file) throws IOException, MalformedBuildFileException {
|
||||
IFileSystem fs = parent.getFileSystem();
|
||||
BufferedReader bufferedReader = new BufferedReader(fs.getReader(file));
|
||||
String line;
|
||||
|
||||
BuildFile bf = new BuildFile();
|
||||
while ((line = bufferedReader.readLine()) != null)
|
||||
bf.addCommand(BuildStep.deserialize(line, parent));
|
||||
bufferedReader.close();
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
public IBuildFile getFromStringList(List<String> list) throws MalformedBuildFileException {
|
||||
BuildFile bf = new BuildFile();
|
||||
|
||||
for (String s : list) {
|
||||
bf.addCommand(BuildStep.deserialize(s, parent));
|
||||
}
|
||||
|
||||
return bf;
|
||||
}
|
||||
|
||||
public IBuildEnvironment createEnvironment() {
|
||||
return new BuildEnvironment();
|
||||
}
|
||||
|
||||
public IBuildSequence createSequence() {
|
||||
return new BuildSequence();
|
||||
}
|
||||
|
||||
public class BuildFile implements IBuildFile {
|
||||
private LinkedList<IBuildStep> commands = new LinkedList<>();
|
||||
|
||||
private void addCommand(IBuildStep b) {
|
||||
commands.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LinkedList<IBuildStep> getCommands() {
|
||||
return commands;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package eu.arcadex.system.build_sequence.implementation;
|
||||
|
||||
|
||||
import eu.arcadex.system.build_sequence.api.*;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public class BuildSequence implements IBuildSequence {
|
||||
private LinkedList<IBuildStep> buildSteps;
|
||||
private boolean inheritance = true;
|
||||
|
||||
public BuildSequence() {
|
||||
this.buildSteps = new LinkedList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInheritance(boolean inheritance) {
|
||||
if (!inheritance)
|
||||
buildSteps.clear();
|
||||
this.inheritance = inheritance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(IBuildStep step) {
|
||||
if (step.getCommand() == IBuildCommand.INH)
|
||||
setInheritance(step.getArgs()[0].equalsIgnoreCase("1"));
|
||||
|
||||
buildSteps.add(step);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(IBuildFile buildFile) {
|
||||
if (!inheritance)
|
||||
buildSteps.clear();
|
||||
buildFile.getCommands().forEach(this::add);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(IBuildEnvironment environment) throws Exception {
|
||||
for (IBuildStep buildStep : buildSteps) {
|
||||
buildStep.execute(environment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package eu.arcadex.system.build_sequence.implementation;
|
||||
|
||||
|
||||
import eu.arcadex.system.build_sequence.Activator;
|
||||
import eu.arcadex.system.build_sequence.CommandLine;
|
||||
import eu.arcadex.system.build_sequence.api.IBuildCommand;
|
||||
import eu.arcadex.system.build_sequence.api.IBuildEnvironment;
|
||||
import eu.arcadex.system.build_sequence.api.IBuildStep;
|
||||
import eu.arcadex.system.file_system.api.IFileSystem;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public class BuildStep implements IBuildStep {
|
||||
private IBuildCommand command;
|
||||
private String[] args;
|
||||
private Activator parent;
|
||||
|
||||
public BuildStep(IBuildCommand command, String[] args, Activator parent) {
|
||||
this.command = command;
|
||||
this.args = args;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
private static IBuildCommand getByName(String name) throws IllegalArgumentException {
|
||||
name = name.trim().toLowerCase();
|
||||
switch (name) {
|
||||
case "cp":
|
||||
case "copy":
|
||||
return IBuildCommand.COPY;
|
||||
case "mkdir":
|
||||
case "mkdirs":
|
||||
return IBuildCommand.MKDIRS;
|
||||
case "link":
|
||||
case "lnk":
|
||||
return IBuildCommand.LNK;
|
||||
case "unzip":
|
||||
return IBuildCommand.UNZIP;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown command " + name);
|
||||
}
|
||||
|
||||
public static IBuildStep deserialize(String string, Activator parent) throws MalformedBuildFileException {
|
||||
String myArgs[] = CommandLine.translateCommandline(string);
|
||||
IBuildCommand cmd = getByName(myArgs[0]);
|
||||
if (myArgs.length - 1 < cmd.getArgumentCount())
|
||||
throw new MalformedBuildFileException("Missing parameters for this procedure");
|
||||
|
||||
return new BuildStep(cmd, Arrays.copyOfRange(myArgs, 1, myArgs.length), parent);
|
||||
}
|
||||
|
||||
public void execute(IBuildEnvironment environment) throws Exception {
|
||||
IFileSystem fileSystem = parent.getFileSystem();
|
||||
switch (command) {
|
||||
case COPY:
|
||||
fileSystem.copy(new File(environment.process(args[0])).getAbsoluteFile().toPath(), new File(environment.process(args[1])).getAbsoluteFile().toPath(), true);
|
||||
break;
|
||||
case MKDIRS:
|
||||
fileSystem.mkdirs(new File(environment.process(args[0])).getAbsoluteFile());
|
||||
break;
|
||||
case LNK:
|
||||
fileSystem.createSymlink(new File(environment.process(args[1])).getAbsoluteFile().toPath(), new File(environment.process(args[0])).getAbsoluteFile().toPath());
|
||||
break;
|
||||
case UNZIP:
|
||||
fileSystem.unzip(new File(environment.process(args[0])).getAbsolutePath(), new File(environment.process(args[1])).getAbsolutePath());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBuildCommand getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package eu.arcadex.system.build_sequence.implementation;
|
||||
|
||||
/**
|
||||
* Created by Daniil on 08.02.2016.
|
||||
*/
|
||||
public class MalformedBuildFileException extends Exception {
|
||||
public MalformedBuildFileException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user