001
014
015 package com.liferay.portal.kernel.search;
016
017 import com.liferay.portal.kernel.dao.search.SearchContainer;
018 import com.liferay.portal.kernel.model.Layout;
019 import com.liferay.portal.kernel.portlet.LiferayPortletURL;
020 import com.liferay.portal.kernel.portlet.PortletProvider;
021 import com.liferay.portal.kernel.portlet.PortletProviderUtil;
022 import com.liferay.portal.kernel.portlet.PortletURLFactoryUtil;
023 import com.liferay.portal.kernel.service.LayoutServiceUtil;
024 import com.liferay.portal.kernel.service.UserLocalServiceUtil;
025 import com.liferay.portal.kernel.theme.ThemeDisplay;
026 import com.liferay.portal.kernel.util.ClassUtil;
027 import com.liferay.portal.kernel.util.GetterUtil;
028 import com.liferay.portal.kernel.util.HttpUtil;
029 import com.liferay.portal.kernel.util.PortalUtil;
030 import com.liferay.portal.kernel.util.PropsUtil;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.StringUtil;
033 import com.liferay.portal.kernel.util.Validator;
034 import com.liferay.portal.kernel.util.WebKeys;
035 import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
036 import com.liferay.portal.kernel.xml.Document;
037 import com.liferay.portal.kernel.xml.Element;
038 import com.liferay.portal.kernel.xml.SAXReaderUtil;
039
040 import java.util.Date;
041
042 import javax.portlet.PortletMode;
043 import javax.portlet.PortletRequest;
044 import javax.portlet.PortletURL;
045 import javax.portlet.WindowState;
046
047 import javax.servlet.http.HttpServletRequest;
048
049
053 public abstract class BaseOpenSearchImpl implements OpenSearch {
054
055 public BaseOpenSearchImpl() {
056 Class<?> clazz = getClass();
057
058 _enabled = GetterUtil.getBoolean(PropsUtil.get(clazz.getName()), true);
059
060 _openSearchURL = StringPool.BLANK;
061 _openSearchDescriptionURL = StringPool.BLANK;
062 }
063
064 public BaseOpenSearchImpl(
065 String openSearchURL, String openSearchDescriptionURL) {
066
067 _openSearchURL = openSearchURL;
068 _openSearchDescriptionURL = openSearchDescriptionURL;
069
070 _enabled = GetterUtil.getBoolean(
071 PropsUtil.get(ClassUtil.getClassName(this)), true);
072 }
073
074 @Override
075 public String getClassName() {
076 return StringPool.BLANK;
077 }
078
079 @Override
080 public boolean isEnabled() {
081 return _enabled;
082 }
083
084 @Override
085 public abstract String search(
086 HttpServletRequest request, long groupId, long userId,
087 String keywords, int startPage, int itemsPerPage, String format)
088 throws SearchException;
089
090 @Override
091 public String search(
092 HttpServletRequest request, long userId, String keywords,
093 int startPage, int itemsPerPage, String format)
094 throws SearchException {
095
096 return search(
097 request, 0, userId, keywords, startPage, itemsPerPage, format);
098 }
099
100 @Override
101 public String search(HttpServletRequest request, String url)
102 throws SearchException {
103
104 try {
105 long userId = PortalUtil.getUserId(request);
106
107 if (userId == 0) {
108 long companyId = PortalUtil.getCompanyId(request);
109
110 userId = UserLocalServiceUtil.getDefaultUserId(companyId);
111 }
112
113 String keywords = GetterUtil.getString(
114 HttpUtil.getParameter(url, "keywords", false));
115 int startPage = GetterUtil.getInteger(
116 HttpUtil.getParameter(url, "p", false), 1);
117 int itemsPerPage = GetterUtil.getInteger(
118 HttpUtil.getParameter(url, "c", false),
119 SearchContainer.DEFAULT_DELTA);
120 String format = GetterUtil.getString(
121 HttpUtil.getParameter(url, "format", false));
122
123 return search(
124 request, userId, keywords, startPage, itemsPerPage, format);
125 }
126 catch (SearchException se) {
127 throw se;
128 }
129 catch (Exception e) {
130 throw new SearchException(e);
131 }
132 }
133
134 protected void addSearchResult(
135 Element root, long groupId, long scopeGroupId, String entryClassName,
136 long entryClassPK, String title, String link, Date updated,
137 String summary, double score, String format) {
138
139 addSearchResult(
140 root, groupId, scopeGroupId, entryClassName, entryClassPK, title,
141 link, updated, summary, new String[0], 0, score, format);
142 }
143
144 protected void addSearchResult(
145 Element root, long groupId, long scopeGroupId, String entryClassName,
146 long entryClassPK, String title, String link, Date updated,
147 String summary, String[] tags, double ratings, double score,
148 String format) {
149
150 if (format.equals("rss")) {
151 addSearchResultRSS(
152 root, groupId, scopeGroupId, entryClassName, entryClassPK,
153 title, link, updated, summary, tags, ratings, score);
154 }
155 else {
156 addSearchResultAtom(
157 root, groupId, scopeGroupId, entryClassName, entryClassPK,
158 title, link, updated, summary, tags, ratings, score);
159 }
160 }
161
162 protected void addSearchResultAtom(
163 Element root, long groupId, long scopeGroupId, String entryClassName,
164 long entryClassPK, String title, String link, Date updated,
165 String summary, String[] tags, double ratings, double score) {
166
167
168
169 Element entry = OpenSearchUtil.addElement(
170 root, "entry", OpenSearchUtil.DEFAULT_NAMESPACE);
171
172
173
174 OpenSearchUtil.addElement(
175 entry, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
176
177
178
179 OpenSearchUtil.addElement(
180 entry, "scopeGroupId", OpenSearchUtil.LIFERAY_NAMESPACE,
181 scopeGroupId);
182
183
184
185 OpenSearchUtil.addElement(
186 entry, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
187 entryClassName);
188
189
190
191 OpenSearchUtil.addElement(
192 entry, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
193 entryClassPK);
194
195
196
197 OpenSearchUtil.addElement(
198 entry, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
199
200
201
202 Element entryLink = OpenSearchUtil.addElement(
203 entry, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
204
205 entryLink.addAttribute("href", link);
206
207
208
209 OpenSearchUtil.addElement(
210 entry, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
211 "urn:uuid:" + PortalUUIDUtil.generate());
212
213
214
215 OpenSearchUtil.addElement(
216 entry, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, updated);
217
218
219
220 OpenSearchUtil.addElement(
221 entry, "summary", OpenSearchUtil.DEFAULT_NAMESPACE, summary);
222
223
224
225 OpenSearchUtil.addElement(
226 entry, "tags", OpenSearchUtil.DEFAULT_NAMESPACE,
227 StringUtil.merge(tags));
228
229
230
231 OpenSearchUtil.addElement(
232 entry, "ratings", OpenSearchUtil.DEFAULT_NAMESPACE, ratings);
233
234
235
236 OpenSearchUtil.addElement(
237 entry, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
238 }
239
240 protected void addSearchResultRSS(
241 Element root, long groupId, long scopeGroupId, String entryClassName,
242 long entryClassPK, String title, String link, Date updated,
243 String summary, String[] tags, double ratings, double score) {
244
245
246
247 Element item = root.addElement("item");
248
249
250
251 OpenSearchUtil.addElement(
252 item, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
253
254
255
256 OpenSearchUtil.addElement(
257 item, "scopeGroupId", OpenSearchUtil.LIFERAY_NAMESPACE,
258 scopeGroupId);
259
260
261
262 OpenSearchUtil.addElement(
263 item, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
264 entryClassName);
265
266
267
268 OpenSearchUtil.addElement(
269 item, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
270 entryClassPK);
271
272
273
274 OpenSearchUtil.addElement(
275 item, "title", OpenSearchUtil.NO_NAMESPACE, title);
276
277
278
279 OpenSearchUtil.addElement(
280 item, "link", OpenSearchUtil.NO_NAMESPACE, link);
281
282
283
284 OpenSearchUtil.addElement(
285 item, "description", OpenSearchUtil.NO_NAMESPACE, summary);
286
287
288
289 OpenSearchUtil.addElement(
290 item, "tags", OpenSearchUtil.NO_NAMESPACE, StringUtil.merge(tags));
291
292
293
294 OpenSearchUtil.addElement(
295 item, "ratings", OpenSearchUtil.NO_NAMESPACE, ratings);
296
297
298
299 OpenSearchUtil.addElement(
300 item, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
301 }
302
303 protected Object[] addSearchResults(
304 String[] queryTerms, String keywords, int startPage, int itemsPerPage,
305 int total, int start, String title, String searchPath, String format,
306 ThemeDisplay themeDisplay) {
307
308 int totalPages = 0;
309
310 if ((total % itemsPerPage) == 0) {
311 totalPages = total / itemsPerPage;
312 }
313 else {
314 totalPages = (total / itemsPerPage) + 1;
315 }
316
317 int previousPage = startPage - 1;
318 int nextPage = startPage + 1;
319
320 Document doc = SAXReaderUtil.createDocument();
321
322 if (format.equals("rss")) {
323 return addSearchResultsRSS(
324 doc, queryTerms, keywords, startPage, itemsPerPage, total,
325 start, totalPages, previousPage, nextPage, title, searchPath,
326 themeDisplay);
327 }
328 else {
329 return addSearchResultsAtom(
330 doc, queryTerms, keywords, startPage, itemsPerPage, total,
331 start, totalPages, previousPage, nextPage, title, searchPath,
332 themeDisplay);
333 }
334 }
335
336 protected Object[] addSearchResultsAtom(
337 Document doc, String[] queryTerms, String keywords, int startPage,
338 int itemsPerPage, int total, int start, int totalPages,
339 int previousPage, int nextPage, String title, String searchPath,
340 ThemeDisplay themeDisplay) {
341
342
343
344 Element root = doc.addElement("feed");
345
346 root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.DEFAULT_NAMESPACE));
347 root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
348 root.add(
349 OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
350
351
352
353 OpenSearchUtil.addElement(
354 root, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
355
356
357
358 OpenSearchUtil.addElement(
359 root, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, new Date());
360
361
362
363 Element author = OpenSearchUtil.addElement(
364 root, "author", OpenSearchUtil.DEFAULT_NAMESPACE);
365
366
367
368 OpenSearchUtil.addElement(
369 author, "name", OpenSearchUtil.DEFAULT_NAMESPACE,
370 themeDisplay.getUserId());
371
372
373
374 OpenSearchUtil.addElement(
375 root, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
376 "urn:uuid:" + PortalUUIDUtil.generate());
377
378
379
380 OpenSearchUtil.addElement(
381 root, "queryTerms", OpenSearchUtil.DEFAULT_NAMESPACE,
382 StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
383
384
385
386 OpenSearchUtil.addElement(
387 root, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
388
389
390
391 OpenSearchUtil.addElement(
392 root, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
393
394
395
396 OpenSearchUtil.addElement(
397 root, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
398
399
400
401 Element query = OpenSearchUtil.addElement(
402 root, "Query", OpenSearchUtil.OS_NAMESPACE);
403
404 query.addAttribute("role", "request");
405 query.addAttribute("searchTerms", keywords);
406 query.addAttribute("startPage", String.valueOf(startPage));
407
408
409
410 String searchURL = getOpenSearchURL(searchPath, themeDisplay);
411
412 OpenSearchUtil.addLink(
413 root, searchURL, "self", keywords, startPage, itemsPerPage);
414 OpenSearchUtil.addLink(
415 root, searchURL, "first", keywords, 1, itemsPerPage);
416
417 if (previousPage > 0) {
418 OpenSearchUtil.addLink(
419 root, searchURL, "previous", keywords, previousPage,
420 itemsPerPage);
421 }
422
423 if (nextPage <= totalPages) {
424 OpenSearchUtil.addLink(
425 root, searchURL, "next", keywords, nextPage, itemsPerPage);
426 }
427
428 OpenSearchUtil.addLink(
429 root, searchURL, "last", keywords, totalPages, itemsPerPage);
430
431 Element link = OpenSearchUtil.addElement(
432 root, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
433
434 link.addAttribute("rel", "search");
435 link.addAttribute(
436 "href", getOpenSearchDescriptionURL(searchPath, themeDisplay));
437 link.addAttribute("type", "application/opensearchdescription+xml");
438
439 return new Object[] {doc, root};
440 }
441
442 protected Object[] addSearchResultsRSS(
443 Document doc, String[] queryTerms, String keywords, int startPage,
444 int itemsPerPage, int total, int start, int totalPages,
445 int previousPage, int nextPage, String title, String searchPath,
446 ThemeDisplay themeDisplay) {
447
448
449
450 Element root = doc.addElement("rss");
451
452 root.addAttribute("version", "2.0");
453 root.add(
454 SAXReaderUtil.createNamespace(
455 "atom", "http:
456 root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
457 root.add(
458 OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
459
460
461
462 Element channel = root.addElement("channel");
463
464
465
466 OpenSearchUtil.addElement(
467 channel, "title", OpenSearchUtil.NO_NAMESPACE, title);
468
469
470
471 OpenSearchUtil.addElement(
472 channel, "link", OpenSearchUtil.NO_NAMESPACE,
473 getOpenSearchURL(searchPath, themeDisplay));
474
475
476
477 OpenSearchUtil.addElement(
478 channel, "description", OpenSearchUtil.NO_NAMESPACE, title);
479
480
481
482 OpenSearchUtil.addElement(
483 channel, "queryTerms", OpenSearchUtil.NO_NAMESPACE,
484 StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
485
486
487
488 OpenSearchUtil.addElement(
489 channel, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
490
491
492
493 OpenSearchUtil.addElement(
494 channel, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
495
496
497
498 OpenSearchUtil.addElement(
499 channel, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
500
501
502
503 Element query = OpenSearchUtil.addElement(
504 channel, "Query", OpenSearchUtil.OS_NAMESPACE);
505
506 query.addAttribute("role", "request");
507 query.addAttribute("searchTerms", keywords);
508 query.addAttribute("startPage", String.valueOf(startPage));
509
510 return new Object[] {doc, channel};
511 }
512
513 protected String getOpenSearchDescriptionURL(
514 String searchPath, ThemeDisplay themeDisplay) {
515
516 if (Validator.isNotNull(_openSearchDescriptionURL)) {
517 return _openSearchDescriptionURL;
518 }
519
520 return themeDisplay.getPortalURL() + searchPath + "_description.xml";
521 }
522
523 protected String getOpenSearchURL(
524 String searchPath, ThemeDisplay themeDisplay) {
525
526 if (Validator.isNotNull(_openSearchURL)) {
527 return _openSearchURL;
528 }
529
530 return themeDisplay.getPortalURL() + searchPath;
531 }
532
533 protected long getPlid(
534 HttpServletRequest request, String portletId, long scopeGroupId)
535 throws Exception {
536
537 Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
538
539 long layoutGroupId = scopeGroupId;
540
541 if (layout != null) {
542 layoutGroupId = layout.getGroupId();
543 }
544
545 long plid = LayoutServiceUtil.getDefaultPlid(
546 layoutGroupId, scopeGroupId, false, portletId);
547
548 if (plid == 0) {
549 plid = LayoutServiceUtil.getDefaultPlid(
550 layoutGroupId, scopeGroupId, true, portletId);
551 }
552
553 if (plid == 0) {
554 if (layout != null) {
555 plid = layout.getPlid();
556 }
557 }
558
559 return plid;
560 }
561
562 protected PortletURL getPortletURL(
563 HttpServletRequest request, String portletId)
564 throws Exception {
565
566 return getPortletURL(request, portletId, 0);
567 }
568
569 protected PortletURL getPortletURL(
570 HttpServletRequest request, String portletId, long scopeGroupId)
571 throws Exception {
572
573 long plid = getPlid(request, portletId, scopeGroupId);
574
575 PortletURL portletURL = PortletURLFactoryUtil.create(
576 request, portletId, plid, PortletRequest.RENDER_PHASE);
577
578 portletURL.setPortletMode(PortletMode.VIEW);
579 portletURL.setWindowState(WindowState.MAXIMIZED);
580
581 return portletURL;
582 }
583
584 protected PortletURL getPortletURL(
585 HttpServletRequest request, String className,
586 PortletProvider.Action action, long scopeGroupId)
587 throws Exception {
588
589 LiferayPortletURL portletURL =
590 (LiferayPortletURL)PortletProviderUtil.getPortletURL(
591 request, className, action);
592
593 long plid = getPlid(request, portletURL.getPortletId(), scopeGroupId);
594
595 portletURL.setPlid(plid);
596
597 portletURL.setPortletMode(PortletMode.VIEW);
598 portletURL.setWindowState(WindowState.MAXIMIZED);
599
600 return portletURL;
601 }
602
603 private final boolean _enabled;
604 private final String _openSearchDescriptionURL;
605 private final String _openSearchURL;
606
607 }