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