
io.vertigo.quarto.plugins.converter.openoffice.AbstractOpenOfficeConverterPlugin Maven / Gradle / Ivy
/**
* vertigo - simple java starter
*
* Copyright (C) 2013, KleeGroup, [email protected] (http://www.kleegroup.com)
* KleeGroup, Centre d'affaire la Boursidiere - BP 159 - 92357 Le Plessis Robinson Cedex - France
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.vertigo.quarto.plugins.converter.openoffice;
import io.vertigo.dynamo.file.FileManager;
import io.vertigo.dynamo.file.model.VFile;
import io.vertigo.dynamo.file.util.TempFile;
import io.vertigo.lang.Activeable;
import io.vertigo.lang.Assertion;
import io.vertigo.lang.WrappedException;
import io.vertigo.quarto.impl.converter.ConverterPlugin;
import java.io.File;
import java.io.IOException;
import java.net.ConnectException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import com.sun.star.beans.PropertyValue;
import com.sun.star.io.XInputStream;
import com.sun.star.io.XOutputStream;
import com.sun.star.lang.XComponent;
import com.sun.star.uno.UnoRuntime;
import com.sun.star.util.XRefreshable;
/**
* Conversion des fichiers à partir de OpenOffice.
* @author npiedeloup
*/
abstract class AbstractOpenOfficeConverterPlugin implements ConverterPlugin, Activeable {
/** Le port par défaut pour accéder à OpenOffice est 8100. */
public static final int DEFAULT_UNO_PORT = 8100;
private static final Logger LOGGER = Logger.getLogger(AbstractOpenOfficeConverterPlugin.class);
private final ExecutorService executors = Executors.newFixedThreadPool(1);
private final FileManager fileManager;
private final String unoHost;
private final int unoPort;
private final int convertTimeoutSeconds;
/**
* Constructeur.
* @param fileManager Manager de gestion des fichiers
* @param unoHost Hote du serveur OpenOffice
* @param unoPort Port de connexion au serveur OpenOffice
* @param convertTimeoutSeconds Convert timeout in seconds
*/
protected AbstractOpenOfficeConverterPlugin(final FileManager fileManager, final String unoHost, final String unoPort, final int convertTimeoutSeconds) {
super();
Assertion.checkNotNull(fileManager);
Assertion.checkArgNotEmpty(unoHost);
Assertion.checkArgument(convertTimeoutSeconds >= 1 && convertTimeoutSeconds <= 900, "Le timeout de conversion est exprimé en seconde et doit-être compris entre 1s et 15min (900s)");
//-----
this.fileManager = fileManager;
this.unoHost = unoHost;
this.unoPort = Integer.valueOf(unoPort);
this.convertTimeoutSeconds = convertTimeoutSeconds;
}
/** {@inheritDoc} */
@Override
public void start() {
//nothing
}
/** {@inheritDoc} */
@Override
public void stop() {
executors.shutdown();
}
/** {@inheritDoc} */
@Override
public final VFile convertToFormat(final VFile file, final String targetFormat) {
Assertion.checkArgNotEmpty(targetFormat);
//-----
return convertToFormat(file, ConverterFormat.find(targetFormat));
}
private VFile convertToFormat(final VFile file, final ConverterFormat targetFormat) {
Assertion.checkNotNull(file);
Assertion.checkNotNull(targetFormat);
// si le format de sortie est celui d'entrée la convertion est inutile
Assertion.checkArgument(!targetFormat.getTypeMime().equals(file.getMimeType()), "Le format de sortie est identique à celui d'entrée ; la conversion est inutile");
//-----
final File inputFile = fileManager.obtainReadOnlyFile(file);
final Callable convertTask = new Callable() {
@Override
public File call() throws Exception {
return doConvertToFormat(inputFile, targetFormat);
}
};
final File targetFile;
try {
final Future targetFileFuture = executors.submit(convertTask);
targetFile = targetFileFuture.get(convertTimeoutSeconds, TimeUnit.SECONDS);
} catch (final Exception e) {
throw new WrappedException("Erreur de conversion du document au format " + targetFormat.name() + " (" + e.getClass().getSimpleName() + ")", e);
}
return fileManager.createFile(targetFile);
}
// On synchronize sur le plugin car OpenOffice supporte mal les accès concurrents.
/**
* @param inputFile Fichier source
* @param targetFormat Format de destination
* @return Fichier resultat
* @throws Exception Exception
*/
synchronized File doConvertToFormat(final File inputFile, final ConverterFormat targetFormat) throws Exception {
try (final OpenOfficeConnection openOfficeConnection = connectOpenOffice()) {
Assertion.checkArgument(inputFile.exists(), "Le document à convertir n''existe pas : {0}", inputFile.getAbsolutePath());
final XComponent xDoc = loadDocument(inputFile, openOfficeConnection);
try {
refreshDocument(xDoc);
LOGGER.debug("Document source chargé");
final File targetFile = new TempFile("edition", '.' + targetFormat.name());
storeDocument(targetFile, xDoc, targetFormat, openOfficeConnection);
LOGGER.debug("Conversion réussie");
return targetFile;
} finally {
xDoc.dispose();
}
}
}
/**
* Ecriture du document.
* @param outputFile Fichier de sortie
* @param xDoc Document OpenOffice source
* @param targetFormat Format de sortie
* @param openOfficeConnection Connection à OpenOffice
* @throws Exception Erreur de traitement
*/
protected abstract void storeDocument(final File outputFile, final XComponent xDoc, final ConverterFormat targetFormat, final OpenOfficeConnection openOfficeConnection) throws Exception;
/**
* Lecture d'un docuement.
* @param inputFile Fichier source
* @param openOfficeConnection Connection à OpenOffice
* @return Document OpenOffice
* @throws Exception Erreur de traitement
*/
protected abstract XComponent loadDocument(final File inputFile, final OpenOfficeConnection openOfficeConnection) throws Exception;
private OpenOfficeConnection connectOpenOffice() throws IOException {
final OpenOfficeConnection openOfficeConnection = new SocketOpenOfficeConnection(unoHost, unoPort);
try {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("connecting to OpenOffice.org on " + unoHost + ":" + unoPort);
}
openOfficeConnection.connect(); //Attention déjà observé : connection ne s'établissant pas et pas de timeout
} catch (final ConnectException connectException) {
//On précise les causes possibles de l'erreur.
final String msg = new StringBuilder()
.append("Dans le fichier OOoBasePath\\Basis\\share\\registry\\data\\org\\openoffice\\Setup.xcu.\n")
.append("Juste après cette ligne-ci : \n")
.append("Il faut ajouter les lignes suivantes :\n")
.append("\n")
.append("socket,host=localhost,port=").append(unoPort).append(";urp; \n")
.append(" \n")
.append("Ensuite, il faut lancer OpenOffice... et l'agent OpenOffice si il tourne.")
.toString();
throw new IOException("Impossible de se connecter à OpenOffice, vérifier qu'il est bien en écoute sur " + unoHost + ":" + unoPort + ".\n\n" + msg, connectException);
}
return openOfficeConnection;
}
private static void refreshDocument(final XComponent document) {
final XRefreshable refreshable = UnoRuntime.queryInterface(XRefreshable.class, document);
if (refreshable != null) {
refreshable.refresh();
}
}
private static PropertyValue[] getFileProperties(final ConverterFormat docType, final XOutputStream outputStream, final XInputStream inputStream) {
Assertion.checkNotNull(docType, "Le type du format de sortie est obligatoire");
Assertion.checkArgument(outputStream == null || inputStream == null, "Les properties pointent soit un fichier local, soit un flux d'entrée, soit un flux de sortie");
final List fileProps = new ArrayList<>(3);
PropertyValue fileProp = new PropertyValue();
fileProp.Name = "Hidden";
fileProp.Value = Boolean.TRUE;
fileProps.add(fileProp);
if (outputStream != null) {
fileProp = new PropertyValue();
fileProp.Name = "OutputStream";
fileProp.Value = outputStream;
fileProps.add(fileProp);
} else if (inputStream != null) {
fileProp = new PropertyValue();
fileProp.Name = "InputStream";
fileProp.Value = inputStream;
fileProps.add(fileProp);
}
if (docType != ConverterFormat.ODT) {
fileProp = new PropertyValue();
fileProp.Name = "FilterName";
fileProp.Value = getFilterNameFromExtension(docType);
fileProps.add(fileProp);
}
return fileProps.toArray(new PropertyValue[fileProps.size()]);
}
/**
* Fournit les proterties de fichier pour un format de conversion.
* @param docType format
* @return Proterties
*/
protected static final PropertyValue[] getFileProperties(final ConverterFormat docType) {
return getFileProperties(docType, null, null);
}
/**
* Fournit les proterties de fichier pour un format de conversion et un flux d'ecriture.
* @param docType docType format
* @param outputStream Flux d'ecriture
* @return Proterties
*/
protected static final PropertyValue[] getFileProperties(final ConverterFormat docType, final XOutputStream outputStream) {
return getFileProperties(docType, outputStream, null);
}
/**
* Fournit les proterties de fichier pour un format de conversion et un flux de lecture.
* @param docType docType format
* @param inputStream Flux de lecture
* @return Proterties
*/
protected static final PropertyValue[] getFileProperties(final ConverterFormat docType, final XInputStream inputStream) {
return getFileProperties(docType, null, inputStream);
}
/**
* @param docType Format de conversion
* @return filterName géré par OpenOffice pour lui préciser le format de conversion
*/
protected static final String getFilterNameFromExtension(final ConverterFormat docType) {
//Liste des filterName géré par OpenOffice.
//la liste est dans :
//OO 3.3 "OpenOffice.org 3\Basis\share\registry\modules\org\openoffice\TypeDetection\Filter\fcfg_writer_filters.xcu"
//OO 3.4 "OpenOffice.org 3\Basis\share\registry\writer.xcd"
switch (docType) {
case PDF:
return "writer_pdf_Export";
case RTF:
return "Rich Text Format";
case DOC:
return "MS Word 97";
case ODT:
return "Open Document Format";
case TXT:
return "Text";
//DOCX et CSV non géré
default:
throw new IllegalArgumentException("Type de document non géré : " + docType);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy