java/ch/wlkl/wsh/War.java
package ch.wlkl.wsh;
import java.io.File;
import java.io.IOException;
import java.util.regex.Pattern;
public class War extends Run {
public static final String Mark = "]";
public static final String Begin = "beg ";
public static final String End = "end ";
final static Option argAna = new Option("", "Cfz");
private final Read<String> dir;
private final Read<String> read;
private final Write<String> write;
File wFile = null;
File home = new File(".");
boolean fromZos = false;
Pattern filter = null;
int iFiles = 0;
int oFiles = 0;
public War (Read<String> dir, Read<String> read, Write<String> write) {
this.dir = dir == null ? new Dir() : dir;
this.read = read == null ? new Cat<String>() : read;
this.write = write == null ? new FileRW() : write;
home = new File(".");
}
public War () {
this(null, null, null);
}
public void run(String... args ) {
iFiles = oFiles = 0;
char fun = ' ';
boolean started = false;
String wFile = null;
String [] ana = new String[2];
if (argAna.analyze(args[0], ana) || ! ("cf".equals(ana[1]) || "xf".equals(ana[1])))
fail("only cf and xf supported not " + args[0]);
fun = ana[1].charAt(0);
if (argAna.analyze(args[1], ana) || (wFile = ana[1]) == null)
fail("file name expected not " + args[1]);
for (int ax = 2; ax < args.length; ax++) {
if (argAna.analyze(args[ax], ana)) {
if ("C".equals(ana[0]))
home = new File(ana[1]);
else if ("f".equals(ana[0]))
filter = "".equals(ana[1]) ? null : Pattern.compile(ana[1]);
else if ("z".equals(ana[0]))
fromZos = ! "0".equals(ana[1]);
else
fail("bad opt " + ana[0]);
} else if (fun == 'c') {
if (! started) {
started = true;
write.reset(wFile);
write.open("w");
}
dir.reset(canonical(new File(home, ana[1])));
dir.open("r");
append(write, dir);
dir.close();
} else if (fun == 'x') {
if (! started) {
started = true;
read.reset(wFile);
read.open("r");
}
extract(read);
} else {
fail("bad fun " + fun);
}
}
if (fun == 'x') {
if (started)
read.close();
Env.env().write("extracted " + oFiles + " of " + iFiles + " files from " + wFile);
} else {
if (started)
write.close();
Env.env().write("added " + oFiles + " of " + iFiles + " files to " + wFile);
}
}
public String filter(String in) {
if (fromZos) {
in = in.replace('.', '/').replaceFirst("\\(", "/");
if (in.charAt(in.length()-1) == ')')
in = in.substring(0, in.length()-1);
}
return filter == null || filter.matcher(in).matches() ? in : null;
}
void append(Write<String> w, String name) {
String line;
String wNm = name.startsWith(canonical(home)) ? name.substring(canonical(home).length()+1) : name;
w.write(Mark + Begin + wNm);
read.reset(name);
read.open("r");
while (null != (line = read.read())) {
w.write(line.startsWith(War.Mark) ? War.Mark + line : line );
}
w.write(Mark + End + wNm);
read.close();
oFiles ++ ;
}
void append(Write<String> w, Read<String> dir) {
String name;
while (null != (name = dir.read())) {
iFiles ++ ;
if (filter(name) != null)
append(w, name);
}
}
String extract(Read<String> r, Write<String> w) {
iFiles ++;
if (w != null)
oFiles ++;
while (true) {
String line = r.read();
if (line == null)
return null;
if (line.startsWith(War.Mark)) {
if (line.startsWith(War.Mark, War.Mark.length()))
line = line.substring(War.Mark.length());
else
return line;
}
if (w != null)
w.write(line);
}
}
void extract(Read<String> r) {
String line;
String name = null;
String out;
int errs = 0;
while (null != (line = r.read())) {
if (! line.startsWith(War.Mark) || ! line.startsWith(War.Begin, War.Mark.length())) {
String l2 = r.read();
if (l2 == null && line.equals(String.valueOf((char) 0x1a)))
break;
say("data outside file line after " + name + " len " + line.length()+ " hex: " + Strings.hex(line) + " ascii: " + line + " befor: " + l2);
if (++errs > 99)
fail("too many errors");
} else {
name = Parser.skipScan(line.substring(War.Begin.length() + War.Mark.length()), Parser.space, Parser.notSpace);
if (name == null)
fail("begin without name");
if (null == (out = filter(name))) {
line = extract(r, null);
} else {
write.reset(new File(home, out).getPath());
write.open("w");
line = extract(r, write);
write.close();
}
if (! line.startsWith(War.Mark) || ! line.startsWith(War.End, War.Mark.length()))
fail("end expected: " + line);
else if (! name.equals(Parser.skipScan(line.substring(War.End.length() + War.Mark.length()), Parser.space, Parser.notSpace)))
fail("begin name " + name + " mismatches end " + line);
}
}
}
public static String canonical(String name) {
return canonical(new File(name));
}
public static String canonical(File file) {
try {
return file.getCanonicalPath();
} catch (IOException e) {
sFail("canonical of " + file + " caught " + e);
return null;
}
}
public static void main(String... args) {
War w = new War();
Env.env().write("begin War " + args.length + " " + (args.length > 0 ? args[0] : ""));
w.run(args);
Env.env().write("end War " + args.length + " " + (args.length > 0 ? args[0] : ""));
}
}