1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.kernel.search;
16  
17  import com.liferay.portal.kernel.dao.search.SearchContainer;
18  import com.liferay.portal.kernel.util.GetterUtil;
19  import com.liferay.portal.kernel.util.HttpUtil;
20  import com.liferay.portal.kernel.util.PropsUtil;
21  import com.liferay.portal.kernel.util.StringPool;
22  import com.liferay.portal.kernel.util.StringUtil;
23  import com.liferay.portal.kernel.util.WebKeys;
24  import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
25  import com.liferay.portal.kernel.xml.Document;
26  import com.liferay.portal.kernel.xml.Element;
27  import com.liferay.portal.kernel.xml.SAXReaderUtil;
28  import com.liferay.portal.model.Layout;
29  import com.liferay.portal.service.LayoutLocalServiceUtil;
30  import com.liferay.portal.service.UserLocalServiceUtil;
31  import com.liferay.portal.theme.ThemeDisplay;
32  import com.liferay.portal.util.PortalUtil;
33  import com.liferay.portlet.PortletURLFactoryUtil;
34  
35  import java.util.Date;
36  
37  import javax.portlet.PortletMode;
38  import javax.portlet.PortletRequest;
39  import javax.portlet.PortletURL;
40  import javax.portlet.WindowState;
41  
42  import javax.servlet.http.HttpServletRequest;
43  
44  /**
45   * <a href="BaseOpenSearchImpl.java.html"><b><i>View Source</i></b></a>
46   *
47   * @author Charles May
48   * @author Brian Wing Shun Chan
49   */
50  public abstract class BaseOpenSearchImpl implements OpenSearch {
51  
52      public boolean isEnabled() {
53          return _enabled;
54      }
55  
56      public abstract String search(
57              HttpServletRequest request, long groupId, long userId,
58              String keywords, int startPage, int itemsPerPage, String format)
59          throws SearchException;
60  
61      public String search(
62              HttpServletRequest request, long userId, String keywords,
63              int startPage, int itemsPerPage, String format)
64          throws SearchException {
65  
66          return search(
67              request, 0, userId, keywords, startPage, itemsPerPage, format);
68      }
69  
70      public String search(HttpServletRequest request, String url)
71          throws SearchException {
72  
73          try {
74              long userId = PortalUtil.getUserId(request);
75  
76              if (userId == 0) {
77                  long companyId = PortalUtil.getCompanyId(request);
78  
79                  userId = UserLocalServiceUtil.getDefaultUserId(companyId);
80              }
81  
82              String keywords = GetterUtil.getString(
83                  HttpUtil.getParameter(url, "keywords", false));
84              int startPage = GetterUtil.getInteger(
85                  HttpUtil.getParameter(url, "p", false), 1);
86              int itemsPerPage = GetterUtil.getInteger(
87                  HttpUtil.getParameter(url, "c", false),
88                  SearchContainer.DEFAULT_DELTA);
89              String format = GetterUtil.getString(
90                  HttpUtil.getParameter(url, "format", false));
91  
92              return search(
93                  request, userId, keywords, startPage, itemsPerPage, format);
94          }
95          catch (SearchException se) {
96              throw se;
97          }
98          catch (Exception e) {
99              throw new SearchException(e);
100         }
101     }
102 
103     protected void addSearchResult(
104         Element root, long groupId, String title, String link, Date updated,
105         String summary, double score, String format) {
106 
107         addSearchResult(
108             root, groupId, title, link, updated, summary, new String[0], 0,
109             score, format);
110     }
111 
112     protected void addSearchResult(
113         Element root, long groupId, String title, String link, Date updated,
114         String summary, String[] tags, double ratings, double score,
115         String format) {
116 
117         if (format.equals("rss")) {
118             addSearchResultRSS(
119                 root, groupId, title, link, updated, summary, tags, ratings,
120                 score);
121         }
122         else {
123             addSearchResultAtom(
124                 root, groupId, title, link, updated, summary, tags, ratings,
125                 score);
126         }
127     }
128 
129     protected void addSearchResultAtom(
130         Element root, long groupId, String title, String link, Date updated,
131         String summary, String[] tags, double ratings, double score) {
132 
133         // entry
134 
135         Element entry = OpenSearchUtil.addElement(
136             root, "entry", OpenSearchUtil.DEFAULT_NAMESPACE);
137 
138         // groupId
139 
140         OpenSearchUtil.addElement(
141             entry, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
142 
143         // title
144 
145         OpenSearchUtil.addElement(
146             entry, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
147 
148         // link
149 
150         Element entryLink = OpenSearchUtil.addElement(
151             entry, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
152 
153         entryLink.addAttribute("href", link);
154 
155         // id
156 
157         OpenSearchUtil.addElement(
158             entry, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
159             "urn:uuid:" + PortalUUIDUtil.generate());
160 
161         // updated
162 
163         OpenSearchUtil.addElement(
164             entry, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, updated);
165 
166         // summary
167 
168         OpenSearchUtil.addElement(
169             entry, "summary", OpenSearchUtil.DEFAULT_NAMESPACE, summary);
170 
171         // tags
172 
173         OpenSearchUtil.addElement(
174             entry, "tags", OpenSearchUtil.DEFAULT_NAMESPACE,
175             StringUtil.merge(tags));
176 
177         // ratings
178 
179         OpenSearchUtil.addElement(
180             entry, "ratings", OpenSearchUtil.DEFAULT_NAMESPACE, ratings);
181 
182         // relevance:score
183 
184         OpenSearchUtil.addElement(
185             entry, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
186     }
187 
188     protected void addSearchResultRSS(
189         Element root, long groupId, String title, String link, Date updated,
190         String summary, String[] tags, double ratings, double score) {
191 
192         // item
193 
194         Element item = root.addElement("item");
195 
196         // groupId
197 
198         OpenSearchUtil.addElement(
199             item, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
200 
201         // title
202 
203         OpenSearchUtil.addElement(
204             item, "title", OpenSearchUtil.NO_NAMESPACE, title);
205 
206         // link
207 
208         OpenSearchUtil.addElement(
209             item, "link", OpenSearchUtil.NO_NAMESPACE, link);
210 
211         // summary
212 
213         OpenSearchUtil.addElement(
214             item, "description", OpenSearchUtil.NO_NAMESPACE, summary);
215 
216         // tags
217 
218         OpenSearchUtil.addElement(
219             item, "tags", OpenSearchUtil.NO_NAMESPACE, StringUtil.merge(tags));
220 
221         // ratings
222 
223         OpenSearchUtil.addElement(
224             item, "ratings", OpenSearchUtil.NO_NAMESPACE, ratings);
225 
226         // relevance:score
227 
228         OpenSearchUtil.addElement(
229             item, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
230     }
231 
232     /**
233      * @deprecated
234      */
235     protected Object[] addSearchResults(
236         String keywords, int startPage, int itemsPerPage, int total, int start,
237         String title, String searchPath, String format,
238         ThemeDisplay themeDisplay) {
239 
240         return addSearchResults(
241             new String[0], keywords, startPage, itemsPerPage, total, start,
242             title, searchPath, format, themeDisplay);
243     }
244 
245     protected Object[] addSearchResults(
246         String[] queryTerms, String keywords, int startPage, int itemsPerPage,
247         int total, int start, String title, String searchPath, String format,
248         ThemeDisplay themeDisplay) {
249 
250         int totalPages = 0;
251 
252         if (total % itemsPerPage == 0) {
253             totalPages = total / itemsPerPage;
254         }
255         else {
256             totalPages = (total / itemsPerPage) + 1;
257         }
258 
259         int previousPage = startPage - 1;
260         int nextPage = startPage + 1;
261 
262         Document doc = SAXReaderUtil.createDocument();
263 
264         if (format.equals("rss")) {
265             return addSearchResultsRSS(
266                 doc, queryTerms, keywords, startPage, itemsPerPage, total,
267                 start, totalPages, previousPage, nextPage, title, searchPath,
268                 themeDisplay);
269         }
270         else {
271             return addSearchResultsAtom(
272                 doc, queryTerms, keywords, startPage, itemsPerPage, total,
273                 start, totalPages, previousPage, nextPage, title, searchPath,
274                 themeDisplay);
275         }
276     }
277 
278     protected Object[] addSearchResultsAtom(
279         Document doc, String[] queryTerms, String keywords, int startPage,
280         int itemsPerPage, int total, int start, int totalPages,
281         int previousPage, int nextPage, String title, String searchPath,
282         ThemeDisplay themeDisplay) {
283 
284         // feed
285 
286         Element root = doc.addElement("feed");
287 
288         root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.DEFAULT_NAMESPACE));
289         root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
290         root.add(
291             OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
292 
293         // title
294 
295         OpenSearchUtil.addElement(
296             root, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
297 
298         // updated
299 
300         OpenSearchUtil.addElement(
301             root, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, new Date());
302 
303         // author
304 
305         Element author = OpenSearchUtil.addElement(
306             root, "author", OpenSearchUtil.DEFAULT_NAMESPACE);
307 
308         // name
309 
310         OpenSearchUtil.addElement(
311             author, "name", OpenSearchUtil.DEFAULT_NAMESPACE,
312             themeDisplay.getUserId());
313 
314         // id
315 
316         OpenSearchUtil.addElement(
317             root, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
318             "urn:uuid:" + PortalUUIDUtil.generate());
319 
320         // queryTerms
321 
322         OpenSearchUtil.addElement(
323             root, "queryTerms", OpenSearchUtil.DEFAULT_NAMESPACE,
324             StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
325 
326         // opensearch:totalResults
327 
328         OpenSearchUtil.addElement(
329             root, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
330 
331         // opensearch:startIndex
332 
333         OpenSearchUtil.addElement(
334             root, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
335 
336         // opensearch:itemsPerPage
337 
338         OpenSearchUtil.addElement(
339             root, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
340 
341         // opensearch:Query
342 
343         Element query = OpenSearchUtil.addElement(
344             root, "Query", OpenSearchUtil.OS_NAMESPACE);
345 
346         query.addAttribute("role", "request");
347         query.addAttribute("searchTerms", keywords);
348         query.addAttribute("startPage", String.valueOf(startPage));
349 
350         // links
351 
352         String searchURL = themeDisplay.getURLPortal() + searchPath;
353 
354         OpenSearchUtil.addLink(
355             root, searchURL, "self", keywords, startPage, itemsPerPage);
356         OpenSearchUtil.addLink(
357             root, searchURL, "first", keywords, 1, itemsPerPage);
358 
359         if (previousPage > 0) {
360             OpenSearchUtil.addLink(
361                 root, searchURL, "previous", keywords, previousPage,
362                 itemsPerPage);
363         }
364 
365         if (nextPage <= totalPages) {
366             OpenSearchUtil.addLink(
367                 root, searchURL, "next", keywords, nextPage, itemsPerPage);
368         }
369 
370         OpenSearchUtil.addLink(
371             root, searchURL, "last", keywords, totalPages, itemsPerPage);
372 
373         Element link = OpenSearchUtil.addElement(
374             root, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
375 
376         link.addAttribute("rel", "search");
377         link.addAttribute("href", searchPath + "_description.xml");
378         link.addAttribute("type", "application/opensearchdescription+xml");
379 
380         return new Object[] {doc, root};
381     }
382 
383     protected Object[] addSearchResultsRSS(
384         Document doc, String[] queryTerms, String keywords, int startPage,
385         int itemsPerPage, int total, int start, int totalPages,
386         int previousPage, int nextPage, String title, String searchPath,
387         ThemeDisplay themeDisplay) {
388 
389         // rss
390 
391         Element root = doc.addElement("rss");
392 
393         root.addAttribute("version", "2.0");
394         root.add(
395             SAXReaderUtil.createNamespace(
396                 "atom", "http://www.w3.org/2005/Atom"));
397         root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
398         root.add(
399             OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
400 
401         // channel
402 
403         Element channel = root.addElement("channel");
404 
405         // title
406 
407         OpenSearchUtil.addElement(
408             channel, "title", OpenSearchUtil.NO_NAMESPACE, title);
409 
410         // link
411 
412         OpenSearchUtil.addElement(
413             channel, "link", OpenSearchUtil.NO_NAMESPACE,
414             themeDisplay.getURLPortal() + searchPath);
415 
416         // description
417 
418         OpenSearchUtil.addElement(
419             channel, "description", OpenSearchUtil.NO_NAMESPACE, title);
420 
421         // queryTerms
422 
423         OpenSearchUtil.addElement(
424             channel, "queryTerms", OpenSearchUtil.NO_NAMESPACE,
425             StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
426 
427         // opensearch:totalResults
428 
429         OpenSearchUtil.addElement(
430             channel, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
431 
432         // opensearch:startIndex
433 
434         OpenSearchUtil.addElement(
435             channel, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
436 
437         // opensearch:itemsPerPage
438 
439         OpenSearchUtil.addElement(
440             channel, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
441 
442         // opensearch:Query
443 
444         Element query = OpenSearchUtil.addElement(
445             channel, "Query", OpenSearchUtil.OS_NAMESPACE);
446 
447         query.addAttribute("role", "request");
448         query.addAttribute("searchTerms", keywords);
449         query.addAttribute("startPage", String.valueOf(startPage));
450 
451         return new Object[] {doc, channel};
452     }
453 
454     protected PortletURL getPortletURL(
455             HttpServletRequest request, String portletId)
456         throws Exception {
457 
458         return getPortletURL(request, portletId, 0);
459     }
460 
461     protected PortletURL getPortletURL(
462             HttpServletRequest request, String portletId, long groupId)
463         throws Exception {
464 
465         long plid = LayoutLocalServiceUtil.getDefaultPlid(
466             groupId, false, portletId);
467 
468         if (plid == 0) {
469             plid = LayoutLocalServiceUtil.getDefaultPlid(
470                 groupId, true, portletId);
471         }
472 
473         if (plid == 0) {
474             Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
475 
476             if (layout != null) {
477                 plid = layout.getPlid();
478             }
479         }
480 
481         PortletURL portletURL = PortletURLFactoryUtil.create(
482             request, portletId, plid, PortletRequest.RENDER_PHASE);
483 
484         portletURL.setWindowState(WindowState.MAXIMIZED);
485         portletURL.setPortletMode(PortletMode.VIEW);
486 
487         return portletURL;
488     }
489 
490     private boolean _enabled = GetterUtil.getBoolean(
491         PropsUtil.get(getClass().getName()), true);
492 
493 }