001/* 002 * (C) Copyright 2006-2015 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Nuxeo - initial API and implementation 018 * 019 */ 020 021package org.nuxeo.ecm.platform.convert.ooomanager; 022 023import java.io.File; 024import java.io.IOException; 025import java.util.ArrayList; 026 027import org.apache.commons.io.FileUtils; 028import org.apache.commons.lang.ArrayUtils; 029import org.apache.commons.logging.Log; 030import org.apache.commons.logging.LogFactory; 031import org.artofsolving.jodconverter.OfficeDocumentConverter; 032import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; 033import org.artofsolving.jodconverter.office.OfficeConnectionProtocol; 034import org.artofsolving.jodconverter.office.OfficeException; 035import org.artofsolving.jodconverter.office.OfficeManager; 036import org.artofsolving.jodconverter.office.OfficeTask; 037 038import org.nuxeo.runtime.api.Framework; 039import org.nuxeo.runtime.model.ComponentContext; 040import org.nuxeo.runtime.model.ComponentInstance; 041import org.nuxeo.runtime.model.DefaultComponent; 042 043/** 044 * @deprecated Since 8.4. See 'soffice' use with {@link org.nuxeo.ecm.platform.convert.plugins.CommandLineConverter} instead 045 */ 046@Deprecated 047public class OOoManagerComponent extends DefaultComponent implements OOoManagerService { 048 049 protected static final Log log = LogFactory.getLog(OOoManagerComponent.class); 050 051 private static final String CONNECTION_PROTOCOL_PROPERTY_KEY = "jod.connection.protocol"; 052 053 private static final String MAX_TASKS_PER_PROCESS_PROPERTY_KEY = "jod.max.tasks.per.process"; 054 055 private static final String OFFICE_HOME_PROPERTY_KEY = "jod.office.home"; 056 057 private static final String TASK_EXECUTION_TIMEOUT_PROPERTY_KEY = "jod.task.execution.timeout"; 058 059 private static final String TASK_QUEUE_TIMEOUT_PROPERTY_KEY = "jod.task.queue.timeout"; 060 061 private static final String TEMPLATE_PROFILE_DIR_PROPERTY_KEY = "jod.template.profile.dir"; 062 063 private static final String OFFICE_PIPES_PROPERTY_KEY = "jod.office.pipes"; 064 065 private static final String OFFICE_PORTS_PROPERTY_KEY = "jod.office.ports"; 066 067 protected static final String CONFIG_EP = "oooManagerConfig"; 068 069 private static OfficeManager officeManager; 070 071 protected OOoManagerDescriptor descriptor = new OOoManagerDescriptor(); 072 073 protected boolean started = false; 074 075 protected boolean starting = false; 076 077 protected boolean shutingdown = false; 078 079 public OOoManagerDescriptor getDescriptor() { 080 return descriptor; 081 } 082 083 @Override 084 public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) { 085 if (CONFIG_EP.equals(extensionPoint)) { 086 OOoManagerDescriptor desc = (OOoManagerDescriptor) contribution; 087 descriptor = desc; 088 } 089 } 090 091 @Override 092 public void deactivate(ComponentContext context) { 093 stopOOoManager(); 094 } 095 096 @Override 097 public OfficeDocumentConverter getDocumentConverter() { 098 if (isOOoManagerStarted()) { 099 return new OfficeDocumentConverter(officeManager); 100 } else { 101 log.error("OfficeManager is not started."); 102 return null; 103 } 104 } 105 106 public void executeTask(OfficeTask task) { 107 if (isOOoManagerStarted()) { 108 officeManager.execute(task); 109 } else { 110 log.error("OfficeManager is not started."); 111 } 112 } 113 114 @Override 115 public void stopOOoManager() { 116 if (isOOoManagerStarted() && !shutingdown) { 117 shutingdown = true; 118 officeManager.stop(); 119 started = false; 120 shutingdown = false; 121 log.debug("Stopping ooo manager."); 122 } else { 123 log.debug("OOoManager already stopped.."); 124 } 125 } 126 127 @Override 128 public void startOOoManager() throws IOException { 129 DefaultOfficeManagerConfiguration configuration = new DefaultOfficeManagerConfiguration(); 130 if (!descriptor.isEnabled()) { 131 return; 132 } 133 134 starting = true; 135 136 try { 137 // Properties configuration 138 String connectionProtocol = Framework.getProperty(CONNECTION_PROTOCOL_PROPERTY_KEY); 139 if (connectionProtocol != null && !"".equals(connectionProtocol)) { 140 if (OfficeConnectionProtocol.PIPE.toString().equals(connectionProtocol)) { 141 ConfigBuilderHelper.hackClassLoader(); 142 configuration.setConnectionProtocol(OfficeConnectionProtocol.PIPE); 143 } else if (OfficeConnectionProtocol.SOCKET.toString().equals(connectionProtocol)) { 144 configuration.setConnectionProtocol(OfficeConnectionProtocol.SOCKET); 145 } 146 } 147 String maxTasksPerProcessProperty = Framework.getProperty(MAX_TASKS_PER_PROCESS_PROPERTY_KEY); 148 if (maxTasksPerProcessProperty != null && !"".equals(maxTasksPerProcessProperty)) { 149 Integer maxTasksPerProcess = Integer.valueOf(maxTasksPerProcessProperty); 150 configuration.setMaxTasksPerProcess(maxTasksPerProcess); 151 } 152 String officeHome = Framework.getProperty(OFFICE_HOME_PROPERTY_KEY); 153 if (officeHome != null && !"".equals(officeHome)) { 154 configuration.setOfficeHome(officeHome); 155 } 156 157 String taskExecutionTimeoutProperty = Framework.getProperty(TASK_EXECUTION_TIMEOUT_PROPERTY_KEY); 158 if (taskExecutionTimeoutProperty != null && !"".equals(taskExecutionTimeoutProperty)) { 159 Long taskExecutionTimeout = Long.valueOf(taskExecutionTimeoutProperty); 160 configuration.setTaskExecutionTimeout(taskExecutionTimeout); 161 } 162 String taskQueueTimeoutProperty = Framework.getProperty(TASK_QUEUE_TIMEOUT_PROPERTY_KEY); 163 if (taskQueueTimeoutProperty != null && !"".equals(taskQueueTimeoutProperty)) { 164 Long taskQueueTimeout = Long.valueOf(taskQueueTimeoutProperty); 165 configuration.setTaskQueueTimeout(taskQueueTimeout); 166 } 167 String templateProfileDir = Framework.getProperty(TEMPLATE_PROFILE_DIR_PROPERTY_KEY); 168 if (templateProfileDir != null && !"".equals(templateProfileDir)) { 169 File templateDirectory = new File(templateProfileDir); 170 if (!templateDirectory.exists()) { 171 try { 172 FileUtils.forceMkdir(templateDirectory); 173 } catch (IOException e) { 174 throw new RuntimeException("I/O Error: could not create JOD templateDirectory"); 175 } 176 } 177 configuration.setTemplateProfileDir(templateDirectory); 178 } 179 180 // Descriptor configuration 181 String pipeNamesProperty = Framework.getProperty(OFFICE_PIPES_PROPERTY_KEY); 182 String[] pipeNames = null; 183 if (pipeNamesProperty != null) { 184 String[] unvalidatedPipeNames = pipeNamesProperty.split(",\\s*"); 185 ArrayList<String> validatedPipeNames = new ArrayList<>(); 186 // Basic validation to avoid empty strings 187 for (int i = 0; i < unvalidatedPipeNames.length; i++) { 188 String tmpPipeName = unvalidatedPipeNames[i].trim(); 189 if (tmpPipeName.length() > 0) { 190 validatedPipeNames.add(tmpPipeName); 191 } 192 } 193 pipeNames = validatedPipeNames.toArray(new String[0]); 194 } else { 195 pipeNames = descriptor.getPipeNames(); 196 } 197 if (pipeNames != null && pipeNames.length != 0) { 198 configuration.setPipeNames(pipeNames); 199 } 200 String portNumbersProperty = Framework.getProperty(OFFICE_PORTS_PROPERTY_KEY); 201 int[] portNumbers = null; 202 if (portNumbersProperty != null) { 203 String[] portStrings = portNumbersProperty.split(",\\s*"); 204 ArrayList<Integer> portList = new ArrayList<>(); 205 for (int i = 0; i < portStrings.length; i++) { 206 try { 207 portList.add(Integer.parseInt(portStrings[i].trim())); 208 } catch (NumberFormatException e) { 209 log.error("Ignoring malformed port number: " + portStrings[i]); 210 } 211 } 212 portNumbers = ArrayUtils.toPrimitive(portList.toArray(new Integer[0])); 213 } else { 214 portNumbers = descriptor.getPortNumbers(); 215 } 216 if (portNumbers != null && portNumbers.length != 0) { 217 configuration.setPortNumbers(portNumbers); 218 } 219 try { 220 officeManager = configuration.buildOfficeManager(); 221 officeManager.start(); 222 started = true; 223 log.debug("Starting ooo manager."); 224 } catch (IllegalStateException | OfficeException e) { 225 started = false; 226 Throwable t = unwrapException(e); 227 log.warn("OpenOffice was not found, JOD Converter " + "won't be available: " + t.getMessage()); 228 } 229 } finally { 230 starting = false; 231 } 232 } 233 234 public Throwable unwrapException(Throwable t) { 235 Throwable cause = t.getCause(); 236 return cause == null ? t : unwrapException(cause); 237 } 238 239 @Override 240 public void applicationStarted(ComponentContext context) { 241 log.info("Starting OOo manager"); 242 Runnable oooStarter = new Runnable() { 243 @Override 244 public void run() { 245 try { 246 startOOoManager(); 247 } catch (IOException e) { 248 log.error("Could not start OOoManager.", e); 249 } 250 } 251 }; 252 Thread oooStarterThread = new Thread(oooStarter); 253 oooStarterThread.setDaemon(true); 254 oooStarterThread.start(); 255 log.info("Started OOo Manager"); 256 } 257 258 @Override 259 public boolean isOOoManagerStarted() { 260 if (shutingdown) { 261 return false; 262 } 263 if (!starting) { 264 return started; 265 } 266 267 // wait a little bit 268 // while we are starting Ooo 269 for (int i = 0; i < 200; i++) { 270 if (starting) { 271 try { 272 Thread.sleep(300); 273 } catch (InterruptedException e) { 274 // NOP 275 } 276 } 277 if (!starting) { 278 return started; 279 } 280 } 281 282 log.error("Timeout on waiting for officeManager to start"); 283 284 return started; 285 } 286 287 public OfficeManager getOfficeManager() { 288 return officeManager; 289 } 290}