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