package me.pbox.command;
import me.pbox.env.Environment;
import me.pbox.option.Opts;
import me.pbox.xml.TemplateUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import java.io.File;
import java.util.*;
/**
* @author Mike Mirzayanov (mirzayanovmr@gmail.com)
*/
public class DescriptorHandler extends DefaultHandler {
private static final Logger logger = Logger.getLogger(DescriptorHandler.class);
private static final List<String> COMMANDS = Arrays.asList("install", "uninstall");
private final Opts opts;
private final List<String> tagStack = new ArrayList<>();
private final List<Attributes> attributesStack = new ArrayList<>();
private String content;
private final File pboxDir;
private final String processCommand;
private final List<String> processedStatements = new ArrayList<>();
private final Set<String> archs = new HashSet<>();
public DescriptorHandler(File pboxDir, String processCommand, Opts opts) {
this.pboxDir = pboxDir;
this.processCommand = processCommand;
this.opts = new Opts(opts);
}
public Opts getOpts() {
return opts;
}
public List<String> getProcessedStatements() {
return Collections.unmodifiableList(processedStatements);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
tagStack.add(localName);
attributesStack.add(attributes);
content = "";
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
content += new String(ch, start, length);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
int index = tagStack.size() - 1;
String tag = tagStack.get(index);
Attributes attributes = attributesStack.get(index);
tagStack.remove(index);
attributesStack.remove(index);
if (tagStack.size() == 1 && !COMMANDS.contains(tag)) {
content = TemplateUtil.process(content, opts);
boolean ok = true;
int attributesLength = attributes.getLength();
for (int i = 0; i < attributesLength; i++) {
String name = attributes.getLocalName(i);
String value = attributes.getValue(i);
String optionValue = opts.get(name) == null ? "" : opts.get(name);
if (!optionValue.equals(value)) {
ok = false;
}
}
if (ok) {
content = TemplateUtil.process(content, opts);
opts.put(tag, content);
//logger.info("Run set operation '" + tag + "':='" + content + "'.");
}
if (tag.equals("archs")) {
String[] items = content.split("[,;]+");
for (String item : items) {
if (!StringUtils.isNoneBlank()) {
archs.add(item);
}
}
String arch = Environment.getArch();
if (archs.contains(arch)) {
opts.put("arch", arch);
} else {
// Prefer 32
if (archs.contains("32")) {
opts.put("arch", "32");
}
if (archs.contains("64")) {
opts.put("arch", "64");
}
}
String chosenArch = opts.get("arch");
if (archs.contains(chosenArch)) {
opts.put("arch", chosenArch);
logger.info("Use version for architecture '" + chosenArch + "'.");
} else {
throw new RuntimeException("Use architecture '" + chosenArch + "', but it is not supported. Supported are '" + content + "'.");
}
}
}
if (tagStack.size() == 2 && tagStack.get(1).equals("install") && processCommand.equals("install")) {
handleInstall(tag);
}
if (tagStack.size() == 2 && tagStack.get(1).equals("uninstall") && processCommand.equals("uninstall")) {
handleUninstall(tag);
}
}
private void handleUninstall(String tag) {
content = TemplateUtil.process(content, opts);
processedStatements.add(content);
String strHomedir = opts.get("homedir");
if (StringUtils.isBlank(strHomedir)) {
throw new RuntimeException("Can't find homedir.");
}
processCommands(tag, new File(strHomedir));
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void handleInstall(String tag) {
content = TemplateUtil.process(content, opts);
processedStatements.add(content);
String strHomedir = opts.get("homedir");
if (StringUtils.isBlank(strHomedir)) {
throw new RuntimeException("Can't find homedir.");
}
File homedir = new File(strHomedir);
homedir.mkdirs();
processCommands(tag, homedir);
}
private void processCommands(String tag, File homedir) {
switch (tag) {
case "copy":
CommandUtil.copy(pboxDir, content, homedir);
break;
case "remove":
CommandUtil.remove(pboxDir, content, homedir);
break;
case "path":
CommandUtil.path(pboxDir, content, homedir);
break;
case "unpath":
CommandUtil.unpath(pboxDir, content, homedir);
break;
case "env":
CommandUtil.env(pboxDir, content, homedir);
break;
case "unenv":
CommandUtil.unenv(pboxDir, content, homedir);
break;
case "msi":
CommandUtil.msi(pboxDir, content, homedir);
break;
case "unmsi":
CommandUtil.unmsi(pboxDir, content, homedir);
break;
case "exec":
CommandUtil.exec(pboxDir, content, homedir);
break;
case "script":
CommandUtil.script(pboxDir, content, homedir);
break;
default:
throw new RuntimeException("Unexpected element '" + tag + "' in install.");
}
}
}