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