如何取消MS Office文件转换为PDF的libreoffice uno api库过程,以防其超过最大允许的时间



我正在使用libreoffice 6.0的uno api库(soffice(将MS Office格式转换为PDF,Soffice Process在服务器模式下为多个Sumultanious请求服务。通常,转换很快,但是在转换一些大文件时,例如XLSX或PPTX,Soffice过程使用100%CPU,转化率最多需要几分钟。这是不可接受的,因为在此期间,同时请求未得到处理。

为了处理这种情况,我尝试使用java.util.concurrent执行某些子任务作为线程,并通过未来接口使用超时控制。但是,只有在转换的原始MS Office文档负载阶段发生悬挂时,它才有效。如果转换过程已经启动,即使发生了超时异常,Soffice流程也不会一次退出100%的加载,而是将文档转换为PDF。程序执行暂停试图处置已加载文档。

通过命令下的Linux下启动了Soffice过程:

Runtime.getRuntime().exec("/usr/lib64/libreoffice/program/soffice, --nologo, --nodefault, --norestore, --nocrashreport, --nolockcheck, --accept=socket,host=localhost,port=8100;urp;");

转换MS Office文件的代码以简化的形式为:

public  void  convertFile(){
xRemoteContext = BootstrapSocketConnector.bootstrap(oooPath);
xRemoteServiceManager = xRemoteContext.getServiceManager();
Object desktop = null;
desktop = xRemoteServiceManager.createInstanceWithContext("com.sun.star.frame.Desktop", xRemoteContext);
xComponentLoader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, desktop);
File mfile = new File(workingDir + myTemplate);
String sUrl = pathToURL(workingDir + myTemplate);
PropertyValue[] propertiesIn;
propertiesIn = new PropertyValue[2];
propertiesIn[0] = property("ReadOnly", Boolean.TRUE);
propertiesIn[1] = property("Hidden", Boolean.TRUE);
XComponent xComp = null;
try {
//xComp = xComponentLoader.loadComponentFromURL(sUrl, "_blank", 0, propertiesIn);
//The same via timeout control
xComp = callLibreLoad(sUrl, propertiesIn);
}
catch (TimeoutException ex) {
if(xComp!= null)
xComp.dispose();
...
}
// save as a PDF
XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, xComp);
PropertyValue[] propertiesOut = new PropertyValue[2];
propertiesOut[0] = property("FilterName", formatfilter);
propertiesOut[1] = property("Overwrite", Boolean.TRUE);
String myResult = workingDir + fileNameOut;
try {
//xStorable.storeToURL(pathToURL(myResult), propertiesOut);
//The same via timeout control
callLibreStore(xStorable,pathToURL(myResult), propertiesOut);
}
catch (TimeoutException ex) {
if(xComp!= null)
 xComp.dispose();
...
}
if(xComp!= null)
 xComp.dispose();
}

函数calllibreload和calllibrestore使用未来接口进行超时控制:

private XComponent callLibreLoad(String sUrl, PropertyValue[] propertiesIn) throws Exception {
XComponent result = null;
ExecutorService executor = Executors.newCachedThreadPool();
Callable<Object> task = new Callable<Object>() {
 public Object call() throws IllegalArgumentException, com.sun.star.io.IOException {
 return xComponentLoader.loadComponentFromURL(sUrl, "_blank", 0, propertiesIn);
 }
};
Future<Object> future = executor.submit(task);
try {
 result = (XComponent) future.get(maxTimeout, TimeUnit.SECONDS); 
} 
finally 
{ future.cancel(true);} 
return result;
}
private void callLibreStore(XStorable xStorable, String sUrl, PropertyValue[] propertiesOut) throws Exception {
Integer result = null;
ExecutorService executor = Executors.newCachedThreadPool();
Runnable task = new Runnable() {
public void run() {
try {
xStorable.storeToURL(sUrl, propertiesOut);
} catch (com.sun.star.io.IOException e) {
log.error(e);
}
}
};
Future future = executor.submit(task);
try {
future.get(maxTimeout, TimeUnit.SECONDS); 
}
finally {
future.cancel(true); // may or may not desire this
}   
}

因此,当函数calllibreload中发生超时异常时,拱腹过程会立即恢复到工作状态。但是,当超时发生以后,在功能callliblestore中,即使超时发生并且转换线程被侵犯,拱座过程仍处于100%的负载状态,持续了一分钟以上,试图处理加载的文档,执行代码xcomp.dispose((。在此期间

State: WAITING on com.sun.star.lib.uno.environments.remote.JobQueue@30af74b8
Total blocked: 455  Total waited: 1 967
Stack trace: 
java.lang.Object.wait(Native Method)
com.sun.star.lib.uno.environments.remote.JobQueue.removeJob(JobQueue.java:207)
com.sun.star.lib.uno.environments.remote.JobQueue.enter(JobQueue.java:316)
com.sun.star.lib.uno.environments.remote.JobQueue.enter(JobQueue.java:289)
com.sun.star.lib.uno.environments.remote.JavaThreadPool.enter(JavaThreadPool.java:81)
com.sun.star.lib.uno.bridges.java_remote.java_remote_bridge.sendRequest(java_remote_bridge.java:618)
com.sun.star.lib.uno.bridges.java_remote.ProxyFactory$Handler.request(ProxyFactory.java:145)
com.sun.star.lib.uno.bridges.java_remote.ProxyFactory$Handler.invoke(ProxyFactory.java:129)
com.sun.proxy.$Proxy211.close(Unknown Source)
com.componentplus.prom.libreoffice.LibreOfficeStationary.closeDocument(LibreOfficeStationary.java:425)
com.componentplus.prom.libreoffice.LibreOfficeStationary.convertFile(LibreOfficeStationary.java:393)
...

如果需要超过允许的时间超过最大的时间,则如何强迫拱腹取消转化为PDF。

一种可能性可能是保存Runtime.getRuntime().exec返回的Process实例,例如。在变量myProc中,然后在需要时致电myProc.destroy()杀死该过程。

最新更新