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 _log.error(e, e);
120 }
121
122 return false;
123 }
124
125 public static boolean isConvertBeforeCompare(String extension) {
126 if (extension.equals("txt")) {
127 return false;
128 }
129
130 String[] conversions = getConversions(extension);
131
132 for (int i = 0; i < conversions.length; i++) {
133 if (conversions[i].equals("txt")) {
134 return true;
135 }
136 }
137
138 return false;
139 }
140
141 public static boolean isEnabled() {
142 try {
143 return PrefsPropsUtil.getBoolean(
144 PropsKeys.OPENOFFICE_SERVER_ENABLED,
145 PropsValues.OPENOFFICE_SERVER_ENABLED);
146 }
147 catch (Exception e) {
148 }
149
150 return false;
151 }
152
153 private DocumentConversionUtil() {
154 _populateConversionsMap("drawing");
155 _populateConversionsMap("presentation");
156 _populateConversionsMap("spreadsheet");
157 _populateConversionsMap("text");
158 }
159
160 private File _convert(
161 String id, InputStream inputStream, String sourceExtension,
162 String targetExtension)
163 throws IOException {
164
165 if (!isEnabled()) {
166 return null;
167 }
168
169 sourceExtension = _fixExtension(sourceExtension);
170 targetExtension = _fixExtension(targetExtension);
171
172 _validate(targetExtension, id);
173
174 String fileName = getFilePath(id, targetExtension);
175
176 File file = new File(fileName);
177
178 if (PropsValues.OPENOFFICE_CACHE_ENABLED && file.exists()) {
179 return file;
180 }
181
182 DocumentFormatRegistry documentFormatRegistry =
183 new DefaultDocumentFormatRegistry();
184
185 DocumentFormat inputDocumentFormat =
186 documentFormatRegistry.getFormatByFileExtension(sourceExtension);
187 DocumentFormat outputDocumentFormat =
188 documentFormatRegistry.getFormatByFileExtension(targetExtension);
189
190 if (inputDocumentFormat == null) {
191 throw new SystemException(
192 "Conversion is not supported from ." + sourceExtension);
193 }
194 else if (!inputDocumentFormat.isImportable()) {
195 throw new SystemException(
196 "Conversion is not supported from " +
197 inputDocumentFormat.getName());
198 }
199 else if (outputDocumentFormat == null) {
200 throw new SystemException(
201 "Conversion is not supported from " +
202 inputDocumentFormat.getName() + " to ." + targetExtension);
203 }
204 else if (!inputDocumentFormat.isExportableTo(outputDocumentFormat)) {
205 throw new SystemException(
206 "Conversion is not supported from " +
207 inputDocumentFormat.getName() + " to " +
208 outputDocumentFormat.getName());
209 }
210
211 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
212 new UnsyncByteArrayOutputStream();
213
214 DocumentConverter documentConverter = _getDocumentConverter();
215
216 documentConverter.convert(
217 inputStream, inputDocumentFormat, unsyncByteArrayOutputStream,
218 outputDocumentFormat);
219
220 FileUtil.write(
221 file, unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
222 unsyncByteArrayOutputStream.size());
223
224 return file;
225 }
226
227 private void _disconnect() {
228 if (_openOfficeConnection != null) {
229 _openOfficeConnection.disconnect();
230 }
231 }
232
233 private String _fixExtension(String extension) {
234 if (extension.equals("htm")) {
235 extension = "html";
236 }
237
238 return extension;
239 }
240
241 private String[] _getConversions(String extension) {
242 extension = _fixExtension(extension);
243
244 String[] conversions = _conversionsMap.get(extension);
245
246 if (conversions == null) {
247 conversions = _DEFAULT_CONVERSIONS;
248 }
249 else {
250 if (ArrayUtil.contains(conversions, extension)) {
251 List<String> conversionsList = new ArrayList<>();
252
253 for (int i = 0; i < conversions.length; i++) {
254 String conversion = conversions[i];
255
256 if (!conversion.equals(extension)) {
257 conversionsList.add(conversion);
258 }
259 }
260
261 conversions = conversionsList.toArray(
262 new String[conversionsList.size()]);
263 }
264 }
265
266 return conversions;
267 }
268
269 private DocumentConverter _getDocumentConverter() {
270 if ((_openOfficeConnection != null) && (_documentConverter != null)) {
271 return _documentConverter;
272 }
273
274 String host = PrefsPropsUtil.getString(
275 PropsKeys.OPENOFFICE_SERVER_HOST);
276 int port = PrefsPropsUtil.getInteger(
277 PropsKeys.OPENOFFICE_SERVER_PORT,
278 PropsValues.OPENOFFICE_SERVER_PORT);
279
280 if (_isRemoteOpenOfficeHost(host)) {
281 _openOfficeConnection = new SocketOpenOfficeConnection(host, port);
282 _documentConverter = new StreamOpenOfficeDocumentConverter(
283 _openOfficeConnection);
284 }
285 else {
286 _openOfficeConnection = new SocketOpenOfficeConnection(port);
287 _documentConverter = new OpenOfficeDocumentConverter(
288 _openOfficeConnection);
289 }
290
291 return _documentConverter;
292 }
293
294 private boolean _isRemoteOpenOfficeHost(String host) {
295 if (Validator.isNotNull(host) && !host.equals(_LOCALHOST_IP) &&
296 !host.startsWith(_LOCALHOST)) {
297
298 return true;
299 }
300 else {
301 return false;
302 }
303 }
304
305 private void _populateConversionsMap(String documentFamily) {
306 Filter filter = new Filter(documentFamily);
307
308 DocumentFormatRegistry documentFormatRegistry =
309 new DefaultDocumentFormatRegistry();
310
311 String[] sourceExtensions = PropsUtil.getArray(
312 PropsKeys.OPENOFFICE_CONVERSION_SOURCE_EXTENSIONS, filter);
313 String[] targetExtensions = PropsUtil.getArray(
314 PropsKeys.OPENOFFICE_CONVERSION_TARGET_EXTENSIONS, filter);
315
316 for (String sourceExtension : sourceExtensions) {
317 List<String> conversions = new SortedArrayList<>();
318
319 DocumentFormat sourceDocumentFormat =
320 documentFormatRegistry.getFormatByFileExtension(
321 sourceExtension);
322
323 if (sourceDocumentFormat == null) {
324 if (_log.isWarnEnabled()) {
325 _log.warn("Invalid source extension " + sourceExtension);
326 }
327
328 continue;
329 }
330
331 for (String targetExtension : targetExtensions) {
332 DocumentFormat targetDocumentFormat =
333 documentFormatRegistry.getFormatByFileExtension(
334 targetExtension);
335
336 if (targetDocumentFormat == null) {
337 if (_log.isWarnEnabled()) {
338 _log.warn(
339 "Invalid target extension " + targetDocumentFormat);
340 }
341
342 continue;
343 }
344
345 if (sourceDocumentFormat.isExportableTo(targetDocumentFormat)) {
346 conversions.add(targetExtension);
347 }
348 }
349
350 if (conversions.isEmpty()) {
351 if (_log.isInfoEnabled()) {
352 _log.info(
353 "There are no conversions supported from " +
354 sourceExtension);
355 }
356 }
357 else {
358 if (_log.isInfoEnabled()) {
359 _log.info(
360 "Conversions supported from " + sourceExtension +
361 " to " + conversions);
362 }
363
364 _conversionsMap.put(
365 sourceExtension,
366 conversions.toArray(new String[conversions.size()]));
367 }
368 }
369 }
370
371 private void _validate(String targetExtension, String id) {
372 if (!Validator.isFileExtension(targetExtension)) {
373 throw new SystemException("Invalid extension: " + targetExtension);
374 }
375
376 if (!Validator.isFileName(id)) {
377 throw new SystemException("Invalid file name: " + id);
378 }
379 }
380
381 private static final String[] _COMPARABLE_FILE_EXTENSIONS =
382 PropsValues.DL_COMPARABLE_FILE_EXTENSIONS;
383
384 private static final String[] _DEFAULT_CONVERSIONS = new String[0];
385
386 private static final String _LOCALHOST = "localhost";
387
388 private static final String _LOCALHOST_IP = "127.0.0.1";
389
390 private static final Log _log = LogFactoryUtil.getLog(
391 DocumentConversionUtil.class);
392
393 private static final DocumentConversionUtil _instance =
394 new DocumentConversionUtil();
395
396 private final Map<String, String[]> _conversionsMap = new HashMap<>();
397 private DocumentConverter _documentConverter;
398 private OpenOfficeConnection _openOfficeConnection;
399
400 }