1
22
23 package com.liferay.portlet.blogs.service.impl;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.search.Hits;
28 import com.liferay.portal.kernel.util.ArrayUtil;
29 import com.liferay.portal.kernel.util.ContentTypes;
30 import com.liferay.portal.kernel.util.GetterUtil;
31 import com.liferay.portal.kernel.util.OrderByComparator;
32 import com.liferay.portal.kernel.util.StringMaker;
33 import com.liferay.portal.kernel.util.Validator;
34 import com.liferay.portal.lucene.LuceneFields;
35 import com.liferay.portal.lucene.LuceneUtil;
36 import com.liferay.portal.model.Group;
37 import com.liferay.portal.model.User;
38 import com.liferay.portal.model.impl.ResourceImpl;
39 import com.liferay.portal.theme.ThemeDisplay;
40 import com.liferay.portal.util.PortalUtil;
41 import com.liferay.portlet.blogs.EntryContentException;
42 import com.liferay.portlet.blogs.EntryDisplayDateException;
43 import com.liferay.portlet.blogs.EntryTitleException;
44 import com.liferay.portlet.blogs.model.BlogsEntry;
45 import com.liferay.portlet.blogs.model.BlogsStatsUser;
46 import com.liferay.portlet.blogs.service.base.BlogsEntryLocalServiceBaseImpl;
47 import com.liferay.portlet.blogs.util.Indexer;
48 import com.liferay.util.Http;
49 import com.liferay.util.HttpUtil;
50 import com.liferay.util.Normalizer;
51 import com.liferay.util.lucene.HitsImpl;
52
53 import java.io.IOException;
54
55 import java.util.Date;
56 import java.util.Iterator;
57 import java.util.List;
58
59 import org.apache.commons.logging.Log;
60 import org.apache.commons.logging.LogFactory;
61 import org.apache.lucene.document.Document;
62 import org.apache.lucene.index.IndexWriter;
63 import org.apache.lucene.search.BooleanClause;
64 import org.apache.lucene.search.BooleanQuery;
65 import org.apache.lucene.search.Searcher;
66
67
75 public class BlogsEntryLocalServiceImpl extends BlogsEntryLocalServiceBaseImpl {
76
77 public BlogsEntry addEntry(
78 long userId, long plid, String title, String content,
79 int displayDateMonth, int displayDateDay, int displayDateYear,
80 int displayDateHour, int displayDateMinute, String[] tagsEntries,
81 boolean addCommunityPermissions, boolean addGuestPermissions,
82 ThemeDisplay themeDisplay)
83 throws PortalException, SystemException {
84
85 return addEntry(
86 null, userId, plid, title, content, displayDateMonth,
87 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
88 tagsEntries, Boolean.valueOf(addCommunityPermissions),
89 Boolean.valueOf(addGuestPermissions), null, null, themeDisplay);
90 }
91
92 public BlogsEntry addEntry(
93 String uuid, long userId, long plid, String title, String content,
94 int displayDateMonth, int displayDateDay, int displayDateYear,
95 int displayDateHour, int displayDateMinute, String[] tagsEntries,
96 boolean addCommunityPermissions, boolean addGuestPermissions,
97 ThemeDisplay themeDisplay)
98 throws PortalException, SystemException {
99
100 return addEntry(
101 uuid, userId, plid, title, content, displayDateMonth,
102 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
103 tagsEntries, Boolean.valueOf(addCommunityPermissions),
104 Boolean.valueOf(addGuestPermissions), null, null, themeDisplay);
105 }
106
107 public BlogsEntry addEntry(
108 long userId, long plid, String title, String content,
109 int displayDateMonth, int displayDateDay, int displayDateYear,
110 int displayDateHour, int displayDateMinute, String[] tagsEntries,
111 String[] communityPermissions, String[] guestPermissions,
112 ThemeDisplay themeDisplay)
113 throws PortalException, SystemException {
114
115 return addEntry(
116 null, userId, plid, title, content, displayDateMonth,
117 displayDateDay, displayDateYear, displayDateHour, displayDateMinute,
118 tagsEntries, null, null, communityPermissions, guestPermissions,
119 themeDisplay);
120 }
121
122 public BlogsEntry addEntry(
123 String uuid, long userId, long plid, String title, String content,
124 int displayDateMonth, int displayDateDay, int displayDateYear,
125 int displayDateHour, int displayDateMinute, String[] tagsEntries,
126 Boolean addCommunityPermissions, Boolean addGuestPermissions,
127 String[] communityPermissions, String[] guestPermissions,
128 ThemeDisplay themeDisplay)
129 throws PortalException, SystemException {
130
131
133 User user = userPersistence.findByPrimaryKey(userId);
134 long groupId = PortalUtil.getPortletGroupId(plid);
135 Date now = new Date();
136
137 Date displayDate = PortalUtil.getDate(
138 displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
139 displayDateMinute, user.getTimeZone(),
140 new EntryDisplayDateException());
141
142 validate(title, content);
143
144 long entryId = counterLocalService.increment();
145
146 BlogsEntry entry = blogsEntryPersistence.create(entryId);
147
148 entry.setUuid(uuid);
149 entry.setGroupId(groupId);
150 entry.setCompanyId(user.getCompanyId());
151 entry.setUserId(user.getUserId());
152 entry.setUserName(user.getFullName());
153 entry.setCreateDate(now);
154 entry.setModifiedDate(now);
155 entry.setTitle(title);
156 entry.setUrlTitle(getUniqueUrlTitle(entryId, groupId, title));
157 entry.setContent(content);
158 entry.setDisplayDate(displayDate);
159
160 blogsEntryPersistence.update(entry);
161
162
164 if ((addCommunityPermissions != null) &&
165 (addGuestPermissions != null)) {
166
167 addEntryResources(
168 entry, addCommunityPermissions.booleanValue(),
169 addGuestPermissions.booleanValue());
170 }
171 else {
172 addEntryResources(entry, communityPermissions, guestPermissions);
173 }
174
175
177 blogsStatsUserLocalService.updateStatsUser(
178 entry.getGroupId(), userId, now);
179
180
182 updateTagsAsset(userId, entry, tagsEntries);
183
184
186 try {
187 Indexer.addEntry(
188 entry.getCompanyId(), entry.getGroupId(), userId, entryId,
189 title, content, tagsEntries);
190 }
191 catch (IOException ioe) {
192 _log.error("Indexing " + entryId, ioe);
193 }
194
195
197 pingGoogle(entry, themeDisplay);
198
199 return entry;
200 }
201
202 public void addEntryResources(
203 long entryId, boolean addCommunityPermissions,
204 boolean addGuestPermissions)
205 throws PortalException, SystemException {
206
207 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
208
209 addEntryResources(entry, addCommunityPermissions, addGuestPermissions);
210 }
211
212 public void addEntryResources(
213 BlogsEntry entry, boolean addCommunityPermissions,
214 boolean addGuestPermissions)
215 throws PortalException, SystemException {
216
217 resourceLocalService.addResources(
218 entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
219 BlogsEntry.class.getName(), entry.getEntryId(), false,
220 addCommunityPermissions, addGuestPermissions);
221 }
222
223 public void addEntryResources(
224 long entryId, String[] communityPermissions,
225 String[] guestPermissions)
226 throws PortalException, SystemException {
227
228 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
229
230 addEntryResources(entry, communityPermissions, guestPermissions);
231 }
232
233 public void addEntryResources(
234 BlogsEntry entry, String[] communityPermissions,
235 String[] guestPermissions)
236 throws PortalException, SystemException {
237
238 resourceLocalService.addModelResources(
239 entry.getCompanyId(), entry.getGroupId(), entry.getUserId(),
240 BlogsEntry.class.getName(), entry.getEntryId(),
241 communityPermissions, guestPermissions);
242 }
243
244 public void deleteEntries(long groupId)
245 throws PortalException, SystemException {
246
247 Iterator itr = blogsEntryPersistence.findByGroupId(groupId).iterator();
248
249 while (itr.hasNext()) {
250 BlogsEntry entry = (BlogsEntry)itr.next();
251
252 deleteEntry(entry);
253 }
254 }
255
256 public void deleteEntry(long entryId)
257 throws PortalException, SystemException {
258
259 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
260
261 deleteEntry(entry);
262 }
263
264 public void deleteEntry(BlogsEntry entry)
265 throws PortalException, SystemException {
266
267
269 try {
270 Indexer.deleteEntry(entry.getCompanyId(), entry.getEntryId());
271 }
272 catch (IOException ioe) {
273 _log.error("Deleting index " + entry.getEntryId(), ioe);
274 }
275
276
278 tagsAssetLocalService.deleteAsset(
279 BlogsEntry.class.getName(), entry.getEntryId());
280
281
283 ratingsStatsLocalService.deleteStats(
284 BlogsEntry.class.getName(), entry.getEntryId());
285
286
288 mbMessageLocalService.deleteDiscussionMessages(
289 BlogsEntry.class.getName(), entry.getEntryId());
290
291
293 resourceLocalService.deleteResource(
294 entry.getCompanyId(), BlogsEntry.class.getName(),
295 ResourceImpl.SCOPE_INDIVIDUAL, entry.getEntryId());
296
297
299 blogsEntryPersistence.remove(entry.getEntryId());
300 }
301
302 public List getCompanyEntries(long companyId, int begin, int end)
303 throws SystemException {
304
305 return blogsEntryPersistence.findByCompanyId(companyId, begin, end);
306 }
307
308 public List getCompanyEntries(
309 long companyId, int begin, int end, OrderByComparator obc)
310 throws SystemException {
311
312 return blogsEntryPersistence.findByCompanyId(
313 companyId, begin, end, obc);
314 }
315
316 public int getCompanyEntriesCount(long companyId) throws SystemException {
317 return blogsEntryPersistence.countByCompanyId(companyId);
318 }
319
320 public BlogsEntry getEntry(long entryId)
321 throws PortalException, SystemException {
322
323 return blogsEntryPersistence.findByPrimaryKey(entryId);
324 }
325
326 public BlogsEntry getEntry(long groupId, String urlTitle)
327 throws PortalException, SystemException {
328
329 return blogsEntryPersistence.findByG_UT(groupId, urlTitle);
330 }
331
332 public List getGroupEntries(long groupId, int begin, int end)
333 throws SystemException {
334
335 return blogsEntryPersistence.findByGroupId(groupId, begin, end);
336 }
337
338 public List getGroupEntries(
339 long groupId, int begin, int end, OrderByComparator obc)
340 throws SystemException {
341
342 return blogsEntryPersistence.findByGroupId(groupId, begin, end, obc);
343 }
344
345 public int getGroupEntriesCount(long groupId) throws SystemException {
346 return blogsEntryPersistence.countByGroupId(groupId);
347 }
348
349 public List getGroupUserEntries(
350 long groupId, long userId, int begin, int end)
351 throws SystemException {
352
353 return blogsEntryPersistence.findByG_U(groupId, userId, begin, end);
354 }
355
356 public int getGroupUserEntriesCount(long groupId, long userId)
357 throws SystemException {
358
359 return blogsEntryPersistence.countByG_U(groupId, userId);
360 }
361
362 public List getNoAssetEntries() throws SystemException {
363 return blogsEntryFinder.findByNoAssets();
364 }
365
366 public List getOrganizationEntries(long organizationId, int begin, int end)
367 throws SystemException {
368
369 return blogsEntryFinder.findByOrganizationId(
370 organizationId, begin, end);
371 }
372
373 public int getOrganizationEntriesCount(long organizationId)
374 throws SystemException {
375
376 return blogsEntryFinder.countByOrganizationId(
377 organizationId);
378 }
379
380 public String getUrlTitle(long entryId, String title) {
381 String urlTitle = String.valueOf(entryId);
382
383 title = title.trim().toLowerCase();
384
385 if (Validator.isNull(title) || Validator.isNumber(title) ||
386 title.equals("rss")) {
387
388 return urlTitle;
389 }
390
391 title = Normalizer.normalizeToAscii(title);
392
393 char[] urlTitleCharArray = title.toCharArray();
394
395 for (int i = 0; i < urlTitleCharArray.length; i++) {
396 char oldChar = urlTitleCharArray[i];
397
398 char newChar = oldChar;
399
400 if ((oldChar == '_') || (Validator.isChar(oldChar)) ||
401 (Validator.isDigit(oldChar))) {
402
403 }
404 else if (ArrayUtil.contains(_URL_TITLE_REPLACE_CHARS, oldChar)) {
405 newChar = '_';
406 }
407 else {
408 return urlTitle;
409 }
410
411 if (oldChar != newChar) {
412 urlTitleCharArray[i] = newChar;
413 }
414 }
415
416 urlTitle = new String(urlTitleCharArray);
417
418 return urlTitle;
419 }
420
421 public void reIndex(String[] ids) throws SystemException {
422 if (LuceneUtil.INDEX_READ_ONLY) {
423 return;
424 }
425
426 long companyId = GetterUtil.getLong(ids[0]);
427
428 IndexWriter writer = null;
429
430 try {
431 writer = LuceneUtil.getWriter(companyId);
432
433 Iterator itr = blogsEntryPersistence.findByCompanyId(
434 companyId).iterator();
435
436 while (itr.hasNext()) {
437 BlogsEntry entry = (BlogsEntry)itr.next();
438
439 long groupId = entry.getGroupId();
440 long userId = entry.getUserId();
441 long entryId = entry.getEntryId();
442 String title = entry.getTitle();
443 String content = entry.getContent();
444
445 String[] tagsEntries = tagsEntryLocalService.getEntryNames(
446 BlogsEntry.class.getName(), entryId);
447
448 try {
449 Document doc = Indexer.getAddEntryDocument(
450 companyId, groupId, userId, entryId, title, content,
451 tagsEntries);
452
453 writer.addDocument(doc);
454 }
455 catch (Exception e1) {
456 _log.error("Reindexing " + entryId, e1);
457 }
458 }
459 }
460 catch (SystemException se) {
461 throw se;
462 }
463 catch (Exception e2) {
464 throw new SystemException(e2);
465 }
466 finally {
467 try {
468 if (writer != null) {
469 LuceneUtil.write(companyId);
470 }
471 }
472 catch (Exception e) {
473 _log.error(e);
474 }
475 }
476 }
477
478 public Hits search(
479 long companyId, long groupId, long userId, String keywords)
480 throws SystemException {
481
482 Searcher searcher = null;
483
484 try {
485 HitsImpl hits = new HitsImpl();
486
487 BooleanQuery contextQuery = new BooleanQuery();
488
489 LuceneUtil.addRequiredTerm(
490 contextQuery, LuceneFields.PORTLET_ID, Indexer.PORTLET_ID);
491
492 if (groupId > 0) {
493 LuceneUtil.addRequiredTerm(
494 contextQuery, LuceneFields.GROUP_ID, groupId);
495 }
496
497 if (userId > 0) {
498 LuceneUtil.addRequiredTerm(
499 contextQuery, LuceneFields.USER_ID, userId);
500 }
501
502 BooleanQuery searchQuery = new BooleanQuery();
503
504 if (Validator.isNotNull(keywords)) {
505 LuceneUtil.addTerm(searchQuery, LuceneFields.TITLE, keywords);
506 LuceneUtil.addTerm(searchQuery, LuceneFields.CONTENT, keywords);
507 LuceneUtil.addTerm(
508 searchQuery, LuceneFields.TAG_ENTRY, keywords);
509 }
510
511 BooleanQuery fullQuery = new BooleanQuery();
512
513 fullQuery.add(contextQuery, BooleanClause.Occur.MUST);
514
515 if (searchQuery.clauses().size() > 0) {
516 fullQuery.add(searchQuery, BooleanClause.Occur.MUST);
517 }
518
519 searcher = LuceneUtil.getSearcher(companyId);
520
521 hits.recordHits(searcher.search(fullQuery), searcher);
522
523 return hits;
524 }
525 catch (Exception e) {
526 return LuceneUtil.closeSearcher(searcher, keywords, e);
527 }
528 }
529
530 public BlogsEntry updateEntry(
531 long userId, long entryId, String title, String content,
532 int displayDateMonth, int displayDateDay, int displayDateYear,
533 int displayDateHour, int displayDateMinute, String[] tagsEntries,
534 ThemeDisplay themeDisplay)
535 throws PortalException, SystemException {
536
537
539 User user = userPersistence.findByPrimaryKey(userId);
540 Date now = new Date();
541
542 Date displayDate = PortalUtil.getDate(
543 displayDateMonth, displayDateDay, displayDateYear, displayDateHour,
544 displayDateMinute, user.getTimeZone(),
545 new EntryDisplayDateException());
546
547 validate(title, content);
548
549 BlogsEntry entry = blogsEntryPersistence.findByPrimaryKey(entryId);
550
551 entry.setModifiedDate(now);
552 entry.setTitle(title);
553 entry.setUrlTitle(
554 getUniqueUrlTitle(entryId, entry.getGroupId(), title));
555 entry.setContent(content);
556 entry.setDisplayDate(displayDate);
557
558 blogsEntryPersistence.update(entry);
559
560
562 BlogsStatsUser statsUser = blogsStatsUserPersistence.fetchByG_U(
563 entry.getGroupId(), entry.getUserId());
564
565 if (statsUser != null) {
566 statsUser.setLastPostDate(now);
567
568 blogsStatsUserPersistence.update(statsUser);
569 }
570
571
573 updateTagsAsset(userId, entry, tagsEntries);
574
575
577 try {
578 Indexer.updateEntry(
579 entry.getCompanyId(), entry.getGroupId(), userId, entryId,
580 title, content, tagsEntries);
581 }
582 catch (IOException ioe) {
583 _log.error("Indexing " + entryId, ioe);
584 }
585
586
588 pingGoogle(entry, themeDisplay);
589
590 return entry;
591 }
592
593 public void updateTagsAsset(
594 long userId, BlogsEntry entry, String[] tagsEntries)
595 throws PortalException, SystemException {
596
597 tagsAssetLocalService.updateAsset(
598 userId, entry.getGroupId(), BlogsEntry.class.getName(),
599 entry.getEntryId(), tagsEntries, null, null, null, null,
600 ContentTypes.TEXT_HTML, entry.getTitle(), null, null, null, 0, 0,
601 null, false);
602 }
603
604 protected String getUniqueUrlTitle(
605 long entryId, long groupId, String title)
606 throws SystemException {
607
608 String urlTitle = getUrlTitle(entryId, title);
609
610 String newUrlTitle = new String(urlTitle);
611
612 for (int i = 1;; i++) {
613 BlogsEntry entry = blogsEntryPersistence.fetchByG_UT(
614 groupId, newUrlTitle);
615
616 if ((entry == null) || (entry.getEntryId() == entryId)) {
617 break;
618 }
619 else {
620 newUrlTitle = urlTitle + "_" + i;
621 }
622 }
623
624 return newUrlTitle;
625 }
626
627 protected void pingGoogle(BlogsEntry entry, ThemeDisplay themeDisplay)
628 throws PortalException, SystemException {
629
630 if (themeDisplay == null) {
631 return;
632 }
633
634 Group group = groupPersistence.findByPrimaryKey(entry.getGroupId());
635
636 String portalURL = PortalUtil.getPortalURL(themeDisplay);
637
638 if ((portalURL.indexOf("://localhost") != -1) ||
639 (portalURL.indexOf("://127.0.0.1") != -1)) {
640
641 return;
642 }
643
644 String layoutURL = PortalUtil.getLayoutURL(themeDisplay);
645
646 StringMaker sm = new StringMaker();
647
648 String name = group.getDescriptiveName();
649 String url = portalURL + layoutURL + "/blogs";
651 String changesURL = portalURL + layoutURL + "/blogs/rss";
652
653 sm.append("http://blogsearch.google.com/ping?name=");
654 sm.append(HttpUtil.encodeURL(name));
655 sm.append("&url=");
656 sm.append(HttpUtil.encodeURL(url));
657 sm.append("&changesURL=");
658 sm.append(HttpUtil.encodeURL(changesURL));
659
660 String location = sm.toString();
661
662 if (_log.isInfoEnabled()) {
663 _log.info("Pinging Google at " + location);
664 }
665
666 try {
667 String response = Http.URLtoString(sm.toString());
668
669 if (_log.isInfoEnabled()) {
670 _log.info("Google ping response: " + response);
671 }
672 }
673 catch (IOException ioe) {
674 _log.error("Unable to ping Google at " + location, ioe);
675 }
676 }
677
678 protected void validate(String title, String content)
679 throws PortalException {
680
681 if (Validator.isNull(title)) {
682 throw new EntryTitleException();
683 }
684 else if (Validator.isNull(content)) {
685 throw new EntryContentException();
686 }
687 }
688
689 private static final char[] _URL_TITLE_REPLACE_CHARS = new char[] {
690 ' ', '.', '-', ',', '/', '\\', '\'', '\"'
691 };
692
693 private static Log _log =
694 LogFactory.getLog(BlogsEntryLocalServiceImpl.class);
695
696 }