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