001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.kernel.dao.db.DB;
018 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020 import com.liferay.portal.kernel.exception.SystemException;
021 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
022 import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayOutputStream;
023 import com.liferay.portal.kernel.json.JSONFactoryUtil;
024 import com.liferay.portal.kernel.json.JSONObject;
025 import com.liferay.portal.kernel.log.Log;
026 import com.liferay.portal.kernel.log.LogFactoryUtil;
027 import com.liferay.portal.kernel.messaging.Message;
028 import com.liferay.portal.kernel.scheduler.SchedulerEngine;
029 import com.liferay.portal.messaging.LayoutsLocalPublisherRequest;
030 import com.liferay.portal.messaging.LayoutsRemotePublisherRequest;
031 import com.liferay.portal.service.base.QuartzLocalServiceBaseImpl;
032
033 import java.io.ByteArrayInputStream;
034 import java.io.ByteArrayOutputStream;
035 import java.io.IOException;
036 import java.io.InputStream;
037 import java.io.ObjectInputStream;
038 import java.io.ObjectOutputStream;
039 import java.io.ObjectStreamClass;
040
041 import java.sql.Connection;
042 import java.sql.PreparedStatement;
043 import java.sql.ResultSet;
044
045 import java.util.ArrayList;
046 import java.util.HashMap;
047 import java.util.List;
048 import java.util.Map;
049 import java.util.Properties;
050
051
055 public class QuartzLocalServiceImpl extends QuartzLocalServiceBaseImpl {
056
057 public void checkQuartzTables() throws SystemException {
058 createQuartzTables();
059 updateQuartzJobDetails();
060 updateQuartzTriggers();
061 }
062
063 protected byte[] convertMessageToJSON(byte[] jobData)
064 throws Exception {
065
066 ObjectInputStream objectInputStream =
067 new BackwardCompatibleObjectInputStream(
068 new UnsyncByteArrayInputStream(jobData));
069
070 Map<Object, Object> jobDataMap =
071 (Map<Object, Object>)objectInputStream.readObject();
072
073 objectInputStream.close();
074
075 Map<Object, Object> tempJobDataMap = new HashMap<Object, Object>(
076 jobDataMap);
077
078 jobDataMap.clear();
079
080 boolean modifiedKeys = false;
081
082 for (Map.Entry<Object, Object> entry : tempJobDataMap.entrySet()) {
083 Object key = entry.getKey();
084
085 if (key instanceof String) {
086 String stringKey = (String)key;
087
088 if (stringKey.startsWith("destination")) {
089 key = SchedulerEngine.DESTINATION_NAME;
090 }
091 else if (stringKey.equals("messageBody")) {
092 key = SchedulerEngine.MESSAGE;
093
094 jobDataMap.put(
095 key, convertOldJsonStringToObject(entry.getValue()));
096
097 continue;
098 }
099 else {
100 key = stringKey.toUpperCase();
101 }
102
103 modifiedKeys = true;
104 }
105
106 jobDataMap.put(key, entry.getValue());
107 }
108
109 Object object = jobDataMap.get(SchedulerEngine.MESSAGE);
110
111 if ((object == null) || (object instanceof String) || !modifiedKeys) {
112 return null;
113 }
114
115 Message message = null;
116
117 if (object instanceof Message) {
118 message = (Message)object;
119 }
120 else {
121 message = new Message();
122
123 message.setPayload(object);
124 }
125
126 String messageJSON = JSONFactoryUtil.serialize(message);
127
128 jobDataMap.put(SchedulerEngine.MESSAGE, messageJSON);
129
130 UnsyncByteArrayOutputStream newJobDataOutputStream =
131 new UnsyncByteArrayOutputStream();
132 ObjectOutputStream objectOutputStream = new ObjectOutputStream(
133 newJobDataOutputStream);
134
135 objectOutputStream.writeObject(jobDataMap);
136
137 objectOutputStream.close();
138
139 return newJobDataOutputStream.toByteArray();
140 }
141
142 @SuppressWarnings("deprecation")
143 protected Object convertOldJsonStringToObject(Object object) {
144 if (!(object instanceof String)) {
145 return null;
146 }
147
148 String jsonString = (String)object;
149
150 JSONObject jsonObject = null;
151
152 try {
153 jsonObject = JSONFactoryUtil.createJSONObject(jsonString);
154 }
155 catch (Exception e) {
156 if (_log.isWarnEnabled()) {
157 _log.warn(e, e);
158 }
159 }
160
161 String oldJavaClass = jsonObject.getString("javaClass");
162
163 if (oldJavaClass.equals(
164 com.liferay.portlet.communities.messaging.
165 LayoutsLocalPublisherRequest.class.getName())) {
166
167 jsonObject.put(
168 "javaClass", LayoutsLocalPublisherRequest.class.getName());
169 }
170 else if (oldJavaClass.equals(
171 com.liferay.portlet.communities.messaging.
172 LayoutsRemotePublisherRequest.class.getName())) {
173
174 jsonObject.put(
175 "javaClass", LayoutsRemotePublisherRequest.class.getName());
176 }
177
178 jsonString = jsonObject.toString();
179
180 return JSONFactoryUtil.deserialize(jsonString);
181 }
182
183 protected byte[] convertPropertiesToMap(byte[] jobData) throws Exception {
184 InputStream inputStream = null;
185
186 try {
187 inputStream = new ByteArrayInputStream(jobData);
188
189 new ObjectInputStream(inputStream);
190
191 return jobData;
192 }
193 catch (Exception e) {
194 Properties properties = new Properties();
195
196 properties.load(inputStream);
197
198 ByteArrayOutputStream byteArrayOutputStream =
199 new ByteArrayOutputStream();
200
201 ObjectOutputStream objectOutputStream = new ObjectOutputStream(
202 byteArrayOutputStream);
203
204 objectOutputStream.writeObject(
205 new HashMap<Object, Object>(properties));
206
207 objectOutputStream.flush();
208
209 return byteArrayOutputStream.toByteArray();
210 }
211 finally {
212 inputStream.close();
213 }
214 }
215
216 protected void createQuartzTables() throws SystemException {
217 Connection con = null;
218 PreparedStatement ps = null;
219 ResultSet rs = null;
220
221 try {
222 con = DataAccess.getConnection();
223
224 ps = con.prepareStatement(
225 "select count(*) from QUARTZ_JOB_DETAILS");
226
227 rs = ps.executeQuery();
228
229 if (rs.next()) {
230 return;
231 }
232 }
233 catch (Exception e) {
234 if (_log.isWarnEnabled()) {
235 _log.warn(e, e);
236 }
237 }
238 finally {
239 DataAccess.cleanUp(con, ps, rs);
240 }
241
242 DB db = DBFactoryUtil.getDB();
243
244 try {
245 db.runSQLTemplate("quartz-tables.sql", false);
246 }
247 catch (Exception e) {
248 throw new SystemException(e);
249 }
250 }
251
252 protected void updateQuartzJobDetails() {
253 Connection con = null;
254 PreparedStatement ps = null;
255 ResultSet rs = null;
256
257 List<Object[]> arrays = new ArrayList<Object[]>();
258
259 try {
260 con = DataAccess.getConnection();
261
262 ps = con.prepareStatement(
263 "select JOB_NAME, JOB_GROUP, JOB_DATA from QUARTZ_JOB_DETAILS");
264
265 rs = ps.executeQuery();
266
267 while (rs.next()) {
268 String jobName = rs.getString("JOB_NAME");
269 String jobGroup = rs.getString("JOB_GROUP");
270 byte[] jobData = rs.getBytes("JOB_DATA");
271
272 jobData = convertPropertiesToMap(jobData);
273 jobData = convertMessageToJSON(jobData);
274
275 if (jobData == null) {
276 continue;
277 }
278
279 Object[] array = new Object[3];
280
281 array[0] = jobName;
282 array[1] = jobGroup;
283 array[2] = jobData;
284
285 arrays.add(array);
286 }
287 }
288 catch (Exception e) {
289 _log.error(e, e);
290 }
291 finally {
292 DataAccess.cleanUp(con, ps, rs);
293 }
294
295 if (arrays.isEmpty()) {
296 return;
297 }
298
299 try {
300 con = DataAccess.getConnection();
301
302 ps = con.prepareStatement(
303 "update QUARTZ_JOB_DETAILS set JOB_DATA = ? where JOB_NAME = " +
304 "? and JOB_GROUP = ?");
305
306 for (Object[] array : arrays) {
307 String jobName = (String)array[0];
308 String jobGroup = (String)array[1];
309 byte[] jobData = (byte[])array[2];
310
311 ps.setBytes(1, jobData);
312 ps.setString(2, jobName);
313 ps.setString(3, jobGroup);
314
315 ps.executeUpdate();
316 }
317 }
318 catch (Exception e) {
319 _log.error(e, e);
320 }
321 finally {
322 DataAccess.cleanUp(con, ps, rs);
323 }
324 }
325
326 protected void updateQuartzTriggers() {
327 DB db = DBFactoryUtil.getDB();
328
329 String dbType = db.getType();
330
331 if (!dbType.equals(DB.TYPE_SYBASE)) {
332 return;
333 }
334
335 Connection con = null;
336 PreparedStatement ps = null;
337 ResultSet rs = null;
338
339 List<Object[]> arrays = new ArrayList<Object[]>();
340
341 try {
342 con = DataAccess.getConnection();
343
344 ps = con.prepareStatement(
345 "select JOB_NAME, JOB_GROUP, JOB_DATA from QUARTZ_TRIGGERS");
346
347 rs = ps.executeQuery();
348
349 while (rs.next()) {
350 String jobName = rs.getString("JOB_NAME");
351 String jobGroup = rs.getString("JOB_GROUP");
352 byte[] jobData = rs.getBytes("JOB_DATA");
353
354 if ((jobData == null) || (jobData.length != 1)) {
355 continue;
356 }
357
358 if (jobData[0] != 0) {
359 continue;
360 }
361
362 Object[] array = new Object[2];
363
364 array[0] = jobName;
365 array[1] = jobGroup;
366
367 arrays.add(array);
368 }
369 }
370 catch (Exception e) {
371 _log.error(e, e);
372 }
373 finally {
374 DataAccess.cleanUp(con, ps, rs);
375 }
376
377 if (arrays.isEmpty()) {
378 return;
379 }
380
381 try {
382 con = DataAccess.getConnection();
383
384 ps = con.prepareStatement(
385 "update QUARTZ_TRIGGERS set JOB_DATA = ? where JOB_NAME = ? " +
386 "and JOB_GROUP = ?");
387
388 for (Object[] array : arrays) {
389 String jobName = (String)array[0];
390 String jobGroup = (String)array[1];
391
392 ps.setBytes(1, null);
393 ps.setString(2, jobName);
394 ps.setString(3, jobGroup);
395
396 ps.executeUpdate();
397 }
398 }
399 catch (Exception e) {
400 _log.error(e, e);
401 }
402 finally {
403 DataAccess.cleanUp(con, ps, rs);
404 }
405 }
406
407 private static Log _log = LogFactoryUtil.getLog(
408 QuartzLocalServiceImpl.class);
409
410 private class BackwardCompatibleObjectInputStream
411 extends ObjectInputStream {
412
413 public BackwardCompatibleObjectInputStream(InputStream inputStream)
414 throws IOException {
415
416 super(inputStream);
417 }
418
419 @Override
420 @SuppressWarnings("deprecation")
421 protected ObjectStreamClass readClassDescriptor()
422 throws ClassNotFoundException, IOException {
423
424 ObjectStreamClass objectStreamClass = super.readClassDescriptor();
425
426 String name = objectStreamClass.getName();
427
428 if (name.equals(Message.class.getName())) {
429 return ObjectStreamClass.lookup(Message.class);
430 }
431 else if (name.equals(
432 com.liferay.portlet.communities.messaging.
433 LayoutsLocalPublisherRequest.class.getName())) {
434
435 return ObjectStreamClass.lookup(
436 LayoutsLocalPublisherRequest.class);
437 }
438 else if (name.equals(
439 com.liferay.portlet.communities.messaging.
440 LayoutsRemotePublisherRequest.class.getName())) {
441
442 return ObjectStreamClass.lookup(
443 LayoutsRemotePublisherRequest.class);
444 }
445 else {
446 return objectStreamClass;
447 }
448 }
449
450 }
451
452 }