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, SystemException {
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 dotExtension = StringPool.PERIOD + extension;
091
092 for (int i = 0; i < _COMPARABLE_FILE_EXTENSIONS.length; i++) {
093 if (StringPool.STAR.equals(_COMPARABLE_FILE_EXTENSIONS[i]) ||
094 dotExtension.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, SystemException {
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 DocumentFormatRegistry documentFormatRegistry =
182 new DefaultDocumentFormatRegistry();
183
184 DocumentFormat inputDocumentFormat =
185 documentFormatRegistry.getFormatByFileExtension(
186 sourceExtension);
187 DocumentFormat outputDocumentFormat =
188 documentFormatRegistry.getFormatByFileExtension(
189 targetExtension);
190
191 if (inputDocumentFormat == null) {
192 throw new SystemException(
193 "Conversion is not supported from ." + sourceExtension);
194 }
195 else if (!inputDocumentFormat.isImportable()) {
196 throw new SystemException(
197 "Conversion is not supported from " +
198 inputDocumentFormat.getName());
199 }
200 else if (outputDocumentFormat == null) {
201 throw new SystemException(
202 "Conversion is not supported from " +
203 inputDocumentFormat.getName() + " to ." +
204 targetExtension);
205 }
206 else if (!inputDocumentFormat.isExportableTo(
207 outputDocumentFormat)) {
208
209 throw new SystemException(
210 "Conversion is not supported from " +
211 inputDocumentFormat.getName() + " to " +
212 outputDocumentFormat.getName());
213 }
214
215 UnsyncByteArrayOutputStream unsyncByteArrayOutputStream =
216 new UnsyncByteArrayOutputStream();
217
218 DocumentConverter documentConverter = _getDocumentConverter();
219
220 documentConverter.convert(
221 inputStream, inputDocumentFormat, unsyncByteArrayOutputStream,
222 outputDocumentFormat);
223
224 FileUtil.write(
225 file, unsyncByteArrayOutputStream.unsafeGetByteArray(), 0,
226 unsyncByteArrayOutputStream.size());
227 }
228
229 return file;
230 }
231
232 private void _disconnect() {
233 if (_openOfficeConnection != null) {
234 _openOfficeConnection.disconnect();
235 }
236 }
237
238 private String _fixExtension(String extension) {
239 if (extension.equals("htm")) {
240 extension = "html";
241 }
242
243 return extension;
244 }
245
246 private String[] _getConversions(String extension) {
247 extension = _fixExtension(extension);
248
249 String[] conversions = _conversionsMap.get(extension);
250
251 if (conversions == null) {
252 conversions = _DEFAULT_CONVERSIONS;
253 }
254 else {
255 if (ArrayUtil.contains(conversions, extension)) {
256 List<String> conversionsList = new ArrayList<String>();
257
258 for (int i = 0; i < conversions.length; i++) {
259 String conversion = conversions[i];
260
261 if (!conversion.equals(extension)) {
262 conversionsList.add(conversion);
263 }
264 }
265
266 conversions = conversionsList.toArray(
267 new String[conversionsList.size()]);
268 }
269 }
270
271 return conversions;
272 }
273
274 private DocumentConverter _getDocumentConverter() throws SystemException {
275 if ((_openOfficeConnection != null) && (_documentConverter != null)) {
276 return _documentConverter;
277 }
278
279 String host = PrefsPropsUtil.getString(
280 PropsKeys.OPENOFFICE_SERVER_HOST);
281 int port = PrefsPropsUtil.getInteger(
282 PropsKeys.OPENOFFICE_SERVER_PORT,
283 PropsValues.OPENOFFICE_SERVER_PORT);
284
285 if (_isRemoteOpenOfficeHost(host)) {
286 _openOfficeConnection = new SocketOpenOfficeConnection(host, port);
287 _documentConverter = new StreamOpenOfficeDocumentConverter(
288 _openOfficeConnection);
289 }
290 else {
291 _openOfficeConnection = new SocketOpenOfficeConnection(port);
292 _documentConverter = new OpenOfficeDocumentConverter(
293 _openOfficeConnection);
294 }
295
296 return _documentConverter;
297 }
298
299 private boolean _isRemoteOpenOfficeHost(String host) {
300 if (Validator.isNotNull(host) && !host.equals(_LOCALHOST_IP) &&
301 !host.startsWith(_LOCALHOST)) {
302
303 return true;
304 }
305 else {
306 return false;
307 }
308 }
309
310 private void _populateConversionsMap(String documentFamily) {
311 Filter filter = new Filter(documentFamily);
312
313 DocumentFormatRegistry documentFormatRegistry =
314 new DefaultDocumentFormatRegistry();
315
316 String[] sourceExtensions = PropsUtil.getArray(
317 PropsKeys.OPENOFFICE_CONVERSION_SOURCE_EXTENSIONS, filter);
318 String[] targetExtensions = PropsUtil.getArray(
319 PropsKeys.OPENOFFICE_CONVERSION_TARGET_EXTENSIONS, filter);
320
321 for (String sourceExtension : sourceExtensions) {
322 List<String> conversions = new SortedArrayList<String>();
323
324 DocumentFormat sourceDocumentFormat =
325 documentFormatRegistry.getFormatByFileExtension(
326 sourceExtension);
327
328 if (sourceDocumentFormat == null) {
329 if (_log.isWarnEnabled()) {
330 _log.warn("Invalid source extension " + sourceExtension);
331 }
332
333 continue;
334 }
335
336 for (String targetExtension : targetExtensions) {
337 DocumentFormat targetDocumentFormat =
338 documentFormatRegistry.getFormatByFileExtension(
339 targetExtension);
340
341 if (targetDocumentFormat == null) {
342 if (_log.isWarnEnabled()) {
343 _log.warn(
344 "Invalid target extension " + targetDocumentFormat);
345 }
346
347 continue;
348 }
349
350 if (sourceDocumentFormat.isExportableTo(targetDocumentFormat)) {
351 conversions.add(targetExtension);
352 }
353 }
354
355 if (conversions.isEmpty()) {
356 if (_log.isInfoEnabled()) {
357 _log.info(
358 "There are no conversions supported from " +
359 sourceExtension);
360 }
361 }
362 else {
363 if (_log.isInfoEnabled()) {
364 _log.info(
365 "Conversions supported from " + sourceExtension +
366 " to " + conversions);
367 }
368
369 _conversionsMap.put(
370 sourceExtension,
371 conversions.toArray(new String[conversions.size()]));
372 }
373 }
374 }
375
376 private void _validate(String targetExtension, String id)
377 throws SystemException {
378
379 if (!Validator.isFileExtension(targetExtension)) {
380 throw new SystemException("Invalid extension: " + targetExtension);
381 }
382
383 if (!Validator.isFileName(id)) {
384 throw new SystemException("Invalid file name: " + id);
385 }
386 }
387
388 private static final String[] _COMPARABLE_FILE_EXTENSIONS =
389 PropsValues.DL_COMPARABLE_FILE_EXTENSIONS;
390
391 private static final String[] _DEFAULT_CONVERSIONS = new String[0];
392
393 private static final String _LOCALHOST = "localhost";
394
395 private static final String _LOCALHOST_IP = "127.0.0.1";
396
397 private static Log _log = LogFactoryUtil.getLog(
398 DocumentConversionUtil.class);
399
400 private static DocumentConversionUtil _instance =
401 new DocumentConversionUtil();
402
403 private Map<String, String[]> _conversionsMap =
404 new HashMap<String, String[]>();
405 private DocumentConverter _documentConverter;
406 private OpenOfficeConnection _openOfficeConnection;
407
408 }