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