/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* Copyright (c) 2014, MPL CodeInside http://codeinside.ru
*/
package ru.codeinside.gses.form.docx;
import ru.codeinside.gses.form.FormConverter;
import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
final public class RemoteService {
static boolean testMode = false;
final Logger logger = Logger.getLogger(getClass().getName());
final Process process;
final File jarFile;
final Thread errorLogger;
final static String JAVA;
final static File JAVA_HOME;
static {
String os = System.getProperty("os.name").toLowerCase();
JAVA = os.contains("win") ? "java.exe" : "java";
JAVA_HOME = new File(System.getProperty("java.home"));
}
BufferedReader reader;
BufferedReader getIn() {
if (reader == null) {
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
}
return reader;
}
OutputStream getOut() {
return process.getOutputStream();
}
boolean isAlive() {
try {
process.exitValue();
return false;
} catch (IllegalThreadStateException e) {
return true;
}
}
void close() {
if (isAlive()) {
close(process.getInputStream());
close(process.getOutputStream());
close(process.getErrorStream());
process.destroy();
}
errorLogger.interrupt();
jarFile.delete();
}
RemoteService() {
try {
jarFile = File.createTempFile("docx_", ".jar");
} catch (IOException e) {
throw new IllegalStateException(e);
}
InputStream is = null;
FileOutputStream fos = null;
try {
if (testMode) {
is = new FileInputStream("target/srv/docx.jar");
} else {
is = getClass().getResourceAsStream("/srv/docx.jar");
if (is == null) {
throw new IllegalStateException("service jar not found!");
}
}
fos = new FileOutputStream(jarFile);
byte[] buffer = new byte[8192];
int count;
while ((count = is.read(buffer)) > 0) {
fos.write(buffer, 0, count);
}
} catch (FileNotFoundException e) {
jarFile.delete();
throw new IllegalStateException(e);
} catch (IOException e) {
jarFile.delete();
throw new IllegalStateException(e);
} finally {
close(fos);
close(is);
}
String java = detectJava();
ProcessBuilder builder = new ProcessBuilder(java,
"-Djava.awt.headless=true", "-Xmx64m", "-Xms16m", "-Xss1m",
"-jar", jarFile.getAbsolutePath()
);
try {
process = builder.start();
} catch (IOException e) {
jarFile.delete();
throw new IllegalStateException(e);
}
final InputStream error = process.getErrorStream();
errorLogger = new Thread(Thread.currentThread().getThreadGroup(), new Runnable() {
@Override
public void run() {
BufferedReader br = new BufferedReader(new InputStreamReader(error));
try {
while (!Thread.interrupted()) {
try {
String s = br.readLine();
if (s == null) {
break;
}
s = s.trim();
if (!s.isEmpty()) {
Logger.getLogger(FormConverter.class.getName()).info(s);
}
} catch (IOException e) {
break;
}
}
} finally {
close(br);
}
}
}, "docxErrorLogger", 64 * 1024);
errorLogger.setDaemon(true);
errorLogger.start();
}
private String detectJava() {
String process = JAVA;
if (!isJava(process)) {
process = absoluteJavaPath(process);
if (!isJava(process)) {
throw new IllegalStateException("Java not found!");
}
}
return process;
}
private boolean isJava(String processName) {
Process process;
try {
process = new ProcessBuilder(processName, "-version").start();
} catch (IOException e) {
return false;
}
boolean ok = false;
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String version = reader.readLine();
if (version != null && version.startsWith("java version")) {
ok = true;
}
} catch (IOException e) {
logger.log(Level.INFO, "io error", e);
} finally {
process.destroy();
close(reader);
}
return ok;
}
private String absoluteJavaPath(String shortName) {
File process = new File(new File(JAVA_HOME, "bin"), shortName);
if (process.exists()) {
return process.getAbsolutePath();
}
throw new IllegalStateException("not found " + process);
}
void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
logger.log(Level.INFO, "io error", e);
}
}
}
}