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