001
014
015 package com.liferay.portlet.documentlibrary.util;
016
017 import com.artofsolving.jodconverter.DefaultDocumentFormatRegistry;
018 import com.artofsolving.jodconverter.DocumentConverter;
019 import com.artofsolving.jodconverter.DocumentFormat;
020 import com.artofsolving.jodconverter.DocumentFormatRegistry;
021 import com.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;
022 import com.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;
023 import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;
024 import com.artofsolving.jodconverter.openoffice.converter.StreamOpenOfficeDocumentConverter;
025
026 import com.liferay.portal.kernel.configuration.Filter;
027 import com.liferay.portal.kernel.exception.SystemException;
028 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
029 import com.liferay.portal.kernel.log.Log;
030 import com.liferay.portal.kernel.log.LogFactoryUtil;
031 import com.liferay.portal.kernel.util.ArrayUtil;
032 import com.liferay.portal.kernel.util.FileUtil;
033 import com.liferay.portal.kernel.util.PropsKeys;
034 import com.liferay.portal.kernel.util.SortedArrayList;
035 import com.liferay.portal.kernel.util.StringBundler;
036 import com.liferay.portal.kernel.util.StringPool;
037 import com.liferay.portal.kernel.util.SystemProperties;
038 import com.liferay.portal.kernel.util.Validator;
039 import com.liferay.portal.util.PrefsPropsUtil;
040 import com.liferay.portal.util.PropsUtil;
041 import com.liferay.portal.util.PropsValues;
042
043 import java.io.File;
044 import java.io.IOException;
045 import java.io.InputStream;
046
047 import java.util.ArrayList;
048 import java.util.HashMap;
049 import java.util.List;
050 import java.util.Map;
051
052
056 public class DocumentConversionUtil {
057
058 public static File convert(
059 String id, InputStream inputStream, String sourceExtension,
060 String targetExtension)
061 throws IOException {
062
063 return _instance._convert(
064 id, inputStream, sourceExtension, targetExtension);
065 }
066
067 public static void disconnect() {
068 _instance._disconnect();
069 }
070
071 public static String[] getConversions(String extension) {
072 return _instance._getConversions(extension);
073 }
074
075 public static String getFilePath(String id, String targetExtension) {
076 StringBundler sb = new StringBundler(5);
077
078 sb.append(SystemProperties.get(SystemProperties.TMP_DIR));
079 sb.append("/liferay/document_conversion/");
080 sb.append(id);
081 sb.append(StringPool.PERIOD);
082 sb.append(targetExtension);
083
084 return sb.toString();
085 }
086
087 public static boolean isComparableVersion(String extension) {
088 boolean enabled = false;
089
090 String periodAndExtension = StringPool.PERIOD.concat(extension);
091
092 for (int i = 0; i < _COMPARABLE_FILE_EXTENSIONS.length; i++) {
093 if (StringPool.STAR.equals(_COMPARABLE_FILE_EXTENSIONS[i]) ||
094 periodAndExtension.equals(_COMPARABLE_FILE_EXTENSIONS[i])) {
095
096 enabled = true;
097
098 break;
099 }
100 }
101
102 if (!enabled) {
103 return false;
104 }
105
106 if (extension.equals("css") || extension.equals("htm") ||
107 extension.equals("html") || extension.equals("js") ||
108 extension.equals("txt") || extension.equals("xml")) {
109
110 return true;
111 }
112
113 try {
114 if (isEnabled() && isConvertBeforeCompare(extension)) {
115 return true;
116 }
117 }
118 catch (Exception e) {
119 if (_log.isErrorEnabled()) {
120 _log.error(e, e);
121 }
122 }
123
124 return false;
125 }
126
127 public static boolean isConvertBeforeCompare(String extension) {
128 if (extension.equals("txt")) {
129 return false;
130 }
131
132 String[] conversions = getConversions(extension);
133
134 for (int i = 0; i < conversions.length; i++) {
135 if (conversions[i].equals("txt")) {
136 return true;
137 }
138 }
139
140 return false;
141 }
142
143 public static boolean isEnabled() {
144 try {
145 return PrefsPropsUtil.getBoolean(
146 PropsKeys.OPENOFFICE_SERVER_ENABLED,
147 PropsValues.OPENOFFICE_SERVER_ENABLED);
148 }
149 catch (Exception e) {
150 }
151
152 return false;
153 }
154
155 private DocumentConversionUtil() {
156 _populateConversionsMap("drawing");
157 _populateConversionsMap("presentation");
158 _populateConversionsMap("spreadsheet");
159 _populateConversionsMap("text");
160 }
161
162 private File _convert(
163 String id, InputStream inputStream, String sourceExtension,
164 String targetExtension)
165 throws IOException {
166
167 if (!isEnabled()) {
168 return null;
169 }
170
171 sourceExtension = _fixExtension(sourceExtension);
172 targetExtension = _fixExtension(targetExtension);
173
174 _validate(targetExtension, id);
175
176 String fileName = getFilePath(id, targetExtension);
177
178 File file = new File(fileName);
179
180 if (PropsValues.OPENOFFICE_CACHE_ENABLED && file.exists()) {
181 return file;
182 }
183
184 DocumentFormatRegistry documentFormatRegistry =
185 new DefaultDocumentFormatRegistry();
186
187 DocumentFormat inputDocumentFormat =
188 documentFormatRegistry.getFormatByFileExtension(sourceExtension);
189 DocumentFormat outputDocumentFormat =
190 documentFormatRegistry.getFormatByFileExtension(targetExtension);
191
192 if (inputDocumentFormat == null) {
193 throw new SystemException(
194 "Conversion is not supported from ." + sourceExtension);
195 }
196 else if (!inputDocumentFormat.isImportable()) {
197 throw new SystemException(
198 "Conversion is not supported from " +
199 inputDocumentFormat.getName());
200 }
201 else if (outputDocumentFormat == null) {
202 throw new SystemException(
203 "Conversion is not supported from " +
204 inputDocumentFormat.getName() + " to ." + targetExtension);
205 }
206 else if (!inputDocumentFormat.isExportableTo(outputDocumentFormat)) {
207 throw new SystemException(
208 "Conversion is not supported from " +
209 inputDocumentFormat.getName() + " to " +
210 outputDocumentFormat.getName());
211 }
212
213 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
214 new UnsyncByteArrayOutputStream();
215
216 DocumentConverter documentConverter = _getDocumentConverter();
217
218 documentConverter.convert(
219 inputStream, inputDocumentFormat, unsyncByteArrayOutputStream,
220 outputDocumentFormat);
221
222 FileUtil.write(
223 file, unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
224 unsyncByteArrayOutputStream.size());
225
226 return file;
227 }
228
229 private void _disconnect() {
230 if (_openOfficeConnection != null) {
231 _openOfficeConnection.disconnect();
232 }
233 }
234
235 private String _fixExtension(String extension) {
236 if (extension.equals("htm")) {
237 extension = "html";
238 }
239
240 return extension;
241 }
242
243 private String[] _getConversions(String extension) {
244 extension = _fixExtension(extension);
245
246 String[] conversions = _conversionsMap.get(extension);
247
248 if (conversions == null) {
249 conversions = _DEFAULT_CONVERSIONS;
250 }
251 else {
252 if (ArrayUtil.contains(conversions, extension)) {
253 List<String> conversionsList = new ArrayList<>();
254
255 for (int i = 0; i < conversions.length; i++) {
256 String conversion = conversions[i];
257
258 if (!conversion.equals(extension)) {
259 conversionsList.add(conversion);
260 }
261 }
262
263 conversions = conversionsList.toArray(
264 new String[conversionsList.size()]);
265 }
266 }
267
268 return conversions;
269 }
270
271 private DocumentConverter _getDocumentConverter() {
272 if ((_openOfficeConnection != null) && (_documentConverter != null)) {
273 return _documentConverter;
274 }
275
276 String host = PrefsPropsUtil.getString(
277 PropsKeys.OPENOFFICE_SERVER_HOST);
278 int port = PrefsPropsUtil.getInteger(
279 PropsKeys.OPENOFFICE_SERVER_PORT,
280 PropsValues.OPENOFFICE_SERVER_PORT);
281
282 if (_isRemoteOpenOfficeHost(host)) {
283 _openOfficeConnection = new SocketOpenOfficeConnection(host, port);
284 _documentConverter = new StreamOpenOfficeDocumentConverter(
285 _openOfficeConnection);
286 }
287 else {
288 _openOfficeConnection = new SocketOpenOfficeConnection(port);
289 _documentConverter = new OpenOfficeDocumentConverter(
290 _openOfficeConnection);
291 }
292
293 return _documentConverter;
294 }
295
296 private boolean _isRemoteOpenOfficeHost(String host) {
297 if (Validator.isNotNull(host) && !host.equals(_LOCALHOST_IP) &&
298 !host.startsWith(_LOCALHOST)) {
299
300 return true;
301 }
302 else {
303 return false;
304 }
305 }
306
307 private void _populateConversionsMap(String documentFamily) {
308 Filter filter = new Filter(documentFamily);
309
310 DocumentFormatRegistry documentFormatRegistry =
311 new DefaultDocumentFormatRegistry();
312
313 String[] sourceExtensions = PropsUtil.getArray(
314 PropsKeys.OPENOFFICE_CONVERSION_SOURCE_EXTENSIONS, filter);
315 String[] targetExtensions = PropsUtil.getArray(
316 PropsKeys.OPENOFFICE_CONVERSION_TARGET_EXTENSIONS, filter);
317
318 for (String sourceExtension : sourceExtensions) {
319 List<String> conversions = new SortedArrayList<>();
320
321 DocumentFormat sourceDocumentFormat =
322 documentFormatRegistry.getFormatByFileExtension(
323 sourceExtension);
324
325 if (sourceDocumentFormat == null) {
326 if (_log.isWarnEnabled()) {
327 _log.warn("Invalid source extension " + sourceExtension);
328 }
329
330 continue;
331 }
332
333 for (String targetExtension : targetExtensions) {
334 DocumentFormat targetDocumentFormat =
335 documentFormatRegistry.getFormatByFileExtension(
336 targetExtension);
337
338 if (targetDocumentFormat == null) {
339 if (_log.isWarnEnabled()) {
340 _log.warn(
341 "Invalid target extension " + targetDocumentFormat);
342 }
343
344 continue;
345 }
346
347 if (sourceDocumentFormat.isExportableTo(targetDocumentFormat)) {
348 conversions.add(targetExtension);
349 }
350 }
351
352 if (conversions.isEmpty()) {
353 if (_log.isInfoEnabled()) {
354 _log.info(
355 "There are no conversions supported from " +
356 sourceExtension);
357 }
358 }
359 else {
360 if (_log.isInfoEnabled()) {
361 _log.info(
362 "Conversions supported from " + sourceExtension +
363 " to " + conversions);
364 }
365
366 _conversionsMap.put(
367 sourceExtension,
368 conversions.toArray(new String[conversions.size()]));
369 }
370 }
371 }
372
373 private void _validate(String targetExtension, String id) {
374 if (!Validator.isFileExtension(targetExtension)) {
375 throw new SystemException("Invalid extension: " + targetExtension);
376 }
377
378 if (!Validator.isFileName(id)) {
379 throw new SystemException("Invalid file name: " + id);
380 }
381 }
382
383 private static final String[] _COMPARABLE_FILE_EXTENSIONS =
384 PropsValues.DL_COMPARABLE_FILE_EXTENSIONS;
385
386 private static final String[] _DEFAULT_CONVERSIONS = new String[0];
387
388 private static final String _LOCALHOST = "localhost";
389
390 private static final String _LOCALHOST_IP = "127.0.0.1";
391
392 private static final Log _log = LogFactoryUtil.getLog(
393 DocumentConversionUtil.class);
394
395 private static final DocumentConversionUtil _instance =
396 new DocumentConversionUtil();
397
398 private final Map<String, String[]> _conversionsMap = new HashMap<>();
399 private DocumentConverter _documentConverter;
400 private OpenOfficeConnection _openOfficeConnection;
401
402 }