package org.openslx.dnbd3;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.filter.Filters;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jdom2.xpath.XPathExpression;
import org.jdom2.xpath.XPathFactory;
public class DNBD3Server {
private static final int CMDSTOP = 0;
private static final int CMDRELOAD = 1;
private static final int CMDINFO = 2;
private static final int CMDCONFIG = 3;
private static final String HOST = "127.0.0.1";
private static final int PORT = 5004;
public void doReload() throws IOException, DNBD3Exception {
Socket sock = new Socket(HOST, PORT);
sendHeader(sock, new DNBD3Header(CMDRELOAD, 0, 0));
receiveHeader(sock);
sock.close();
}
public void doShutdown() throws IOException, DNBD3Exception {
Socket sock = new Socket(HOST, PORT);
sendHeader(sock, new DNBD3Header(CMDSTOP, 0, 0));
receiveHeader(sock);
sock.close();
}
public void addImage(DNBD3Image image) throws IOException, DNBD3Exception {
Element rootNode = new Element("dnbd3-server");
Element imageNode = new Element("image");
imageNode.setAttribute(new Attribute("group", image.getGroup()));
imageNode.setAttribute(new Attribute("atime", image.getAtime()));
imageNode.setAttribute(new Attribute("vid", String.valueOf(image.getVid())));
imageNode.setAttribute(new Attribute("rid", String.valueOf(image.getRid())));
imageNode.setAttribute(new Attribute("file", image.getPath()));
imageNode.setAttribute(new Attribute("servers", image.getServers()));
imageNode.setAttribute(new Attribute("cache_file", image.getCache()));
rootNode.addContent(imageNode);
Document doc = new Document(rootNode);
Socket sock = new Socket(HOST, PORT);
OutputStream os = sock.getOutputStream();
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
sendHeader(sock, new DNBD3Header(CMDCONFIG, outputter.outputString(doc).length(), 0));
outputter.output(doc, os);
receiveHeader(sock);
sock.close();
}
public List<DNBD3Image> getImages() throws IOException, DNBD3Exception {
List<DNBD3Image> images = new ArrayList<DNBD3Image>();
Socket sock = new Socket(HOST, PORT);
sendHeader(sock, new DNBD3Header(CMDINFO, 0, 0));
receiveHeader(sock);
try {
String group, atime, path, servers, cache;
int vid, rid;
InputStream is = sock.getInputStream();
SAXBuilder builder = new SAXBuilder();
Document document = (Document) builder.build(is);
XPathFactory xpfac = XPathFactory.instance();
XPathExpression<Element> xp;
xp = xpfac.compile("//dnbd3-server/images/image", Filters.element());
for (Element e : xp.evaluate(document)) {
group = e.getAttributeValue("group");
atime = e.getAttributeValue("atime");
vid = Integer.parseInt(e.getAttributeValue("vid"));
rid = Integer.parseInt(e.getAttributeValue("rid"));
path = e.getAttributeValue("file");
servers = e.getAttributeValue("servers");
cache = e.getAttributeValue("cache_file");
images.add(new DNBD3Image(group, atime, vid, rid, path, servers, cache));
}
} catch (JDOMException ex) {
ex.printStackTrace();
}
sock.close();
return images;
}
public List<DNBD3Client> getClients() throws IOException, DNBD3Exception {
List<DNBD3Client> clients = new ArrayList<DNBD3Client>();
Socket sock = new Socket(HOST, PORT);
sendHeader(sock, new DNBD3Header(CMDINFO, 0, 0));
receiveHeader(sock);
try {
String ip, image;
InputStream is = sock.getInputStream();
SAXBuilder builder = new SAXBuilder();
Document document = (Document) builder.build(is);
XPathFactory xpfac = XPathFactory.instance();
XPathExpression<Element> xp;
xp = xpfac.compile("//dnbd3-server/clients/client", Filters.element());
for (Element e : xp.evaluate(document)) {
ip = e.getAttributeValue("ip");
image = e.getAttributeValue("file");
clients.add(new DNBD3Client(ip, image));
}
} catch (JDOMException ex) {
ex.printStackTrace();
}
sock.close();
return clients;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private void sendHeader(Socket sock, DNBD3Header header) throws IOException {
OutputStream os = sock.getOutputStream();
os.write(header.toByteArray());
}
private DNBD3Header receiveHeader(Socket sock) throws IOException, DNBD3Exception {
DNBD3Header header = new DNBD3Header();
InputStream is = sock.getInputStream();
byte[] bytes = ByteBuffer.allocate(12).array();
is.read(bytes, 0, 12);
header.fromByteArray(bytes);
switch (header.getError()) {
case 0:
return header;
case DNBD3Header.ERROR_IMAGE_NOT_FOUND:
throw new DNBD3Exception(DNBD3Header.ERROR_IMAGE_NOT_FOUND,
"Image file does not exist or is not readable");
case DNBD3Header.ERROR_IMAGE_ALREADY_EXISTS:
throw new DNBD3Exception(DNBD3Header.ERROR_IMAGE_ALREADY_EXISTS,
"Image with given vid and rid already exists");
case DNBD3Header.ERROR_CONFIG_FILE_PERMISSIONS:
throw new DNBD3Exception(DNBD3Header.ERROR_CONFIG_FILE_PERMISSIONS,
"Config file is not writable");
default:
throw new DNBD3Exception(DNBD3Header.ERROR_UNKNOWN,
"Unknown error, something went horribly wrong...");
}
}
}