001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.search;
016    
017    import com.liferay.portal.kernel.dao.search.SearchContainer;
018    import com.liferay.portal.kernel.util.GetterUtil;
019    import com.liferay.portal.kernel.util.HttpUtil;
020    import com.liferay.portal.kernel.util.PropsUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.WebKeys;
024    import com.liferay.portal.kernel.uuid.PortalUUIDUtil;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.Element;
027    import com.liferay.portal.kernel.xml.SAXReaderUtil;
028    import com.liferay.portal.model.Layout;
029    import com.liferay.portal.service.LayoutServiceUtil;
030    import com.liferay.portal.service.UserLocalServiceUtil;
031    import com.liferay.portal.theme.ThemeDisplay;
032    import com.liferay.portal.util.PortalUtil;
033    import com.liferay.portlet.PortletURLFactoryUtil;
034    
035    import java.util.Date;
036    
037    import javax.portlet.PortletMode;
038    import javax.portlet.PortletRequest;
039    import javax.portlet.PortletURL;
040    import javax.portlet.WindowState;
041    
042    import javax.servlet.http.HttpServletRequest;
043    
044    /**
045     * @author Charles May
046     * @author Brian Wing Shun Chan
047     */
048    public abstract class BaseOpenSearchImpl implements OpenSearch {
049    
050            public BaseOpenSearchImpl() {
051                    _enabled = GetterUtil.getBoolean(
052                            PropsUtil.get(getClass().getName()), true);
053            }
054    
055            @Override
056            public boolean isEnabled() {
057                    return _enabled;
058            }
059    
060            @Override
061            public abstract String search(
062                            HttpServletRequest request, long groupId, long userId,
063                            String keywords, int startPage, int itemsPerPage, String format)
064                    throws SearchException;
065    
066            @Override
067            public String search(
068                            HttpServletRequest request, long userId, String keywords,
069                            int startPage, int itemsPerPage, String format)
070                    throws SearchException {
071    
072                    return search(
073                            request, 0, userId, keywords, startPage, itemsPerPage, format);
074            }
075    
076            @Override
077            public String search(HttpServletRequest request, String url)
078                    throws SearchException {
079    
080                    try {
081                            long userId = PortalUtil.getUserId(request);
082    
083                            if (userId == 0) {
084                                    long companyId = PortalUtil.getCompanyId(request);
085    
086                                    userId = UserLocalServiceUtil.getDefaultUserId(companyId);
087                            }
088    
089                            String keywords = GetterUtil.getString(
090                                    HttpUtil.getParameter(url, "keywords", false));
091                            int startPage = GetterUtil.getInteger(
092                                    HttpUtil.getParameter(url, "p", false), 1);
093                            int itemsPerPage = GetterUtil.getInteger(
094                                    HttpUtil.getParameter(url, "c", false),
095                                    SearchContainer.DEFAULT_DELTA);
096                            String format = GetterUtil.getString(
097                                    HttpUtil.getParameter(url, "format", false));
098    
099                            return search(
100                                    request, userId, keywords, startPage, itemsPerPage, format);
101                    }
102                    catch (SearchException se) {
103                            throw se;
104                    }
105                    catch (Exception e) {
106                            throw new SearchException(e);
107                    }
108            }
109    
110            protected void addSearchResult(
111                    Element root, long groupId, long scopeGroupId, String entryClassName,
112                    long entryClassPK, String title, String link, Date updated,
113                    String summary, double score, String format) {
114    
115                    addSearchResult(
116                            root, groupId, scopeGroupId, entryClassName, entryClassPK, title,
117                            link, updated, summary, new String[0], 0, score, format);
118            }
119    
120            protected void addSearchResult(
121                    Element root, long groupId, long scopeGroupId, String entryClassName,
122                    long entryClassPK, String title, String link, Date updated,
123                    String summary, String[] tags, double ratings, double score,
124                    String format) {
125    
126                    if (format.equals("rss")) {
127                            addSearchResultRSS(
128                                    root, groupId, scopeGroupId, entryClassName, entryClassPK,
129                                    title, link, updated, summary, tags, ratings, score);
130                    }
131                    else {
132                            addSearchResultAtom(
133                                    root, groupId, scopeGroupId, entryClassName, entryClassPK,
134                                    title, link, updated, summary, tags, ratings, score);
135                    }
136            }
137    
138            protected void addSearchResultAtom(
139                    Element root, long groupId, long scopeGroupId, String entryClassName,
140                    long entryClassPK, String title, String link, Date updated,
141                    String summary, String[] tags, double ratings, double score) {
142    
143                    // entry
144    
145                    Element entry = OpenSearchUtil.addElement(
146                            root, "entry", OpenSearchUtil.DEFAULT_NAMESPACE);
147    
148                    // groupId
149    
150                    OpenSearchUtil.addElement(
151                            entry, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
152    
153                    // scopeGroupId
154    
155                    OpenSearchUtil.addElement(
156                            entry, "scopeGroupId", OpenSearchUtil.LIFERAY_NAMESPACE,
157                            scopeGroupId);
158    
159                    // entryClassName
160    
161                    OpenSearchUtil.addElement(
162                            entry, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
163                            entryClassName);
164    
165                    // entryClassPK
166    
167                    OpenSearchUtil.addElement(
168                            entry, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
169                            entryClassPK);
170    
171                    // title
172    
173                    OpenSearchUtil.addElement(
174                            entry, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
175    
176                    // link
177    
178                    Element entryLink = OpenSearchUtil.addElement(
179                            entry, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
180    
181                    entryLink.addAttribute("href", link);
182    
183                    // id
184    
185                    OpenSearchUtil.addElement(
186                            entry, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
187                            "urn:uuid:" + PortalUUIDUtil.generate());
188    
189                    // updated
190    
191                    OpenSearchUtil.addElement(
192                            entry, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, updated);
193    
194                    // summary
195    
196                    OpenSearchUtil.addElement(
197                            entry, "summary", OpenSearchUtil.DEFAULT_NAMESPACE, summary);
198    
199                    // tags
200    
201                    OpenSearchUtil.addElement(
202                            entry, "tags", OpenSearchUtil.DEFAULT_NAMESPACE,
203                            StringUtil.merge(tags));
204    
205                    // ratings
206    
207                    OpenSearchUtil.addElement(
208                            entry, "ratings", OpenSearchUtil.DEFAULT_NAMESPACE, ratings);
209    
210                    // relevance:score
211    
212                    OpenSearchUtil.addElement(
213                            entry, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
214            }
215    
216            protected void addSearchResultRSS(
217                    Element root, long groupId, long scopeGroupId, String entryClassName,
218                    long entryClassPK, String title, String link, Date updated,
219                    String summary, String[] tags, double ratings, double score) {
220    
221                    // item
222    
223                    Element item = root.addElement("item");
224    
225                    // groupId
226    
227                    OpenSearchUtil.addElement(
228                            item, "groupId", OpenSearchUtil.LIFERAY_NAMESPACE, groupId);
229    
230                    // scopeGroupId
231    
232                    OpenSearchUtil.addElement(
233                            item, "scopeGroupId", OpenSearchUtil.LIFERAY_NAMESPACE,
234                            scopeGroupId);
235    
236                    // entryClassName
237    
238                    OpenSearchUtil.addElement(
239                            item, "entryClassName", OpenSearchUtil.LIFERAY_NAMESPACE,
240                            entryClassName);
241    
242                    // entryClassPK
243    
244                    OpenSearchUtil.addElement(
245                            item, "entryClassPK", OpenSearchUtil.LIFERAY_NAMESPACE,
246                            entryClassPK);
247    
248                    // title
249    
250                    OpenSearchUtil.addElement(
251                            item, "title", OpenSearchUtil.NO_NAMESPACE, title);
252    
253                    // link
254    
255                    OpenSearchUtil.addElement(
256                            item, "link", OpenSearchUtil.NO_NAMESPACE, link);
257    
258                    // summary
259    
260                    OpenSearchUtil.addElement(
261                            item, "description", OpenSearchUtil.NO_NAMESPACE, summary);
262    
263                    // tags
264    
265                    OpenSearchUtil.addElement(
266                            item, "tags", OpenSearchUtil.NO_NAMESPACE, StringUtil.merge(tags));
267    
268                    // ratings
269    
270                    OpenSearchUtil.addElement(
271                            item, "ratings", OpenSearchUtil.NO_NAMESPACE, ratings);
272    
273                    // relevance:score
274    
275                    OpenSearchUtil.addElement(
276                            item, "score", OpenSearchUtil.RELEVANCE_NAMESPACE, score);
277            }
278    
279            /**
280             * @deprecated As of 6.1.0
281             */
282            @Deprecated
283            protected Object[] addSearchResults(
284                    String keywords, int startPage, int itemsPerPage, int total, int start,
285                    String title, String searchPath, String format,
286                    ThemeDisplay themeDisplay) {
287    
288                    return addSearchResults(
289                            new String[0], keywords, startPage, itemsPerPage, total, start,
290                            title, searchPath, format, themeDisplay);
291            }
292    
293            protected Object[] addSearchResults(
294                    String[] queryTerms, String keywords, int startPage, int itemsPerPage,
295                    int total, int start, String title, String searchPath, String format,
296                    ThemeDisplay themeDisplay) {
297    
298                    int totalPages = 0;
299    
300                    if ((total % itemsPerPage) == 0) {
301                            totalPages = total / itemsPerPage;
302                    }
303                    else {
304                            totalPages = (total / itemsPerPage) + 1;
305                    }
306    
307                    int previousPage = startPage - 1;
308                    int nextPage = startPage + 1;
309    
310                    Document doc = SAXReaderUtil.createDocument();
311    
312                    if (format.equals("rss")) {
313                            return addSearchResultsRSS(
314                                    doc, queryTerms, keywords, startPage, itemsPerPage, total,
315                                    start, totalPages, previousPage, nextPage, title, searchPath,
316                                    themeDisplay);
317                    }
318                    else {
319                            return addSearchResultsAtom(
320                                    doc, queryTerms, keywords, startPage, itemsPerPage, total,
321                                    start, totalPages, previousPage, nextPage, title, searchPath,
322                                    themeDisplay);
323                    }
324            }
325    
326            protected Object[] addSearchResultsAtom(
327                    Document doc, String[] queryTerms, String keywords, int startPage,
328                    int itemsPerPage, int total, int start, int totalPages,
329                    int previousPage, int nextPage, String title, String searchPath,
330                    ThemeDisplay themeDisplay) {
331    
332                    // feed
333    
334                    Element root = doc.addElement("feed");
335    
336                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.DEFAULT_NAMESPACE));
337                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
338                    root.add(
339                            OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
340    
341                    // title
342    
343                    OpenSearchUtil.addElement(
344                            root, "title", OpenSearchUtil.DEFAULT_NAMESPACE, title);
345    
346                    // updated
347    
348                    OpenSearchUtil.addElement(
349                            root, "updated", OpenSearchUtil.DEFAULT_NAMESPACE, new Date());
350    
351                    // author
352    
353                    Element author = OpenSearchUtil.addElement(
354                            root, "author", OpenSearchUtil.DEFAULT_NAMESPACE);
355    
356                    // name
357    
358                    OpenSearchUtil.addElement(
359                            author, "name", OpenSearchUtil.DEFAULT_NAMESPACE,
360                            themeDisplay.getUserId());
361    
362                    // id
363    
364                    OpenSearchUtil.addElement(
365                            root, "id", OpenSearchUtil.DEFAULT_NAMESPACE,
366                            "urn:uuid:" + PortalUUIDUtil.generate());
367    
368                    // queryTerms
369    
370                    OpenSearchUtil.addElement(
371                            root, "queryTerms", OpenSearchUtil.DEFAULT_NAMESPACE,
372                            StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
373    
374                    // opensearch:totalResults
375    
376                    OpenSearchUtil.addElement(
377                            root, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
378    
379                    // opensearch:startIndex
380    
381                    OpenSearchUtil.addElement(
382                            root, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
383    
384                    // opensearch:itemsPerPage
385    
386                    OpenSearchUtil.addElement(
387                            root, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
388    
389                    // opensearch:Query
390    
391                    Element query = OpenSearchUtil.addElement(
392                            root, "Query", OpenSearchUtil.OS_NAMESPACE);
393    
394                    query.addAttribute("role", "request");
395                    query.addAttribute("searchTerms", keywords);
396                    query.addAttribute("startPage", String.valueOf(startPage));
397    
398                    // links
399    
400                    String searchURL = themeDisplay.getURLPortal() + searchPath;
401    
402                    OpenSearchUtil.addLink(
403                            root, searchURL, "self", keywords, startPage, itemsPerPage);
404                    OpenSearchUtil.addLink(
405                            root, searchURL, "first", keywords, 1, itemsPerPage);
406    
407                    if (previousPage > 0) {
408                            OpenSearchUtil.addLink(
409                                    root, searchURL, "previous", keywords, previousPage,
410                                    itemsPerPage);
411                    }
412    
413                    if (nextPage <= totalPages) {
414                            OpenSearchUtil.addLink(
415                                    root, searchURL, "next", keywords, nextPage, itemsPerPage);
416                    }
417    
418                    OpenSearchUtil.addLink(
419                            root, searchURL, "last", keywords, totalPages, itemsPerPage);
420    
421                    Element link = OpenSearchUtil.addElement(
422                            root, "link", OpenSearchUtil.DEFAULT_NAMESPACE);
423    
424                    link.addAttribute("rel", "search");
425                    link.addAttribute("href", searchPath + "_description.xml");
426                    link.addAttribute("type", "application/opensearchdescription+xml");
427    
428                    return new Object[] {doc, root};
429            }
430    
431            protected Object[] addSearchResultsRSS(
432                    Document doc, String[] queryTerms, String keywords, int startPage,
433                    int itemsPerPage, int total, int start, int totalPages,
434                    int previousPage, int nextPage, String title, String searchPath,
435                    ThemeDisplay themeDisplay) {
436    
437                    // rss
438    
439                    Element root = doc.addElement("rss");
440    
441                    root.addAttribute("version", "2.0");
442                    root.add(
443                            SAXReaderUtil.createNamespace(
444                                    "atom", "http://www.w3.org/2005/Atom"));
445                    root.add(OpenSearchUtil.getNamespace(OpenSearchUtil.OS_NAMESPACE));
446                    root.add(
447                            OpenSearchUtil.getNamespace(OpenSearchUtil.RELEVANCE_NAMESPACE));
448    
449                    // channel
450    
451                    Element channel = root.addElement("channel");
452    
453                    // title
454    
455                    OpenSearchUtil.addElement(
456                            channel, "title", OpenSearchUtil.NO_NAMESPACE, title);
457    
458                    // link
459    
460                    OpenSearchUtil.addElement(
461                            channel, "link", OpenSearchUtil.NO_NAMESPACE,
462                            themeDisplay.getURLPortal() + searchPath);
463    
464                    // description
465    
466                    OpenSearchUtil.addElement(
467                            channel, "description", OpenSearchUtil.NO_NAMESPACE, title);
468    
469                    // queryTerms
470    
471                    OpenSearchUtil.addElement(
472                            channel, "queryTerms", OpenSearchUtil.NO_NAMESPACE,
473                            StringUtil.merge(queryTerms, StringPool.COMMA_AND_SPACE));
474    
475                    // opensearch:totalResults
476    
477                    OpenSearchUtil.addElement(
478                            channel, "totalResults", OpenSearchUtil.OS_NAMESPACE, total);
479    
480                    // opensearch:startIndex
481    
482                    OpenSearchUtil.addElement(
483                            channel, "startIndex", OpenSearchUtil.OS_NAMESPACE, start + 1);
484    
485                    // opensearch:itemsPerPage
486    
487                    OpenSearchUtil.addElement(
488                            channel, "itemsPerPage", OpenSearchUtil.OS_NAMESPACE, itemsPerPage);
489    
490                    // opensearch:Query
491    
492                    Element query = OpenSearchUtil.addElement(
493                            channel, "Query", OpenSearchUtil.OS_NAMESPACE);
494    
495                    query.addAttribute("role", "request");
496                    query.addAttribute("searchTerms", keywords);
497                    query.addAttribute("startPage", String.valueOf(startPage));
498    
499                    return new Object[] {doc, channel};
500            }
501    
502            protected PortletURL getPortletURL(
503                            HttpServletRequest request, String portletId)
504                    throws Exception {
505    
506                    return getPortletURL(request, portletId, 0);
507            }
508    
509            protected PortletURL getPortletURL(
510                            HttpServletRequest request, String portletId, long scopeGroupId)
511                    throws Exception {
512    
513                    Layout layout = (Layout)request.getAttribute(WebKeys.LAYOUT);
514    
515                    long layoutGroupId = scopeGroupId;
516    
517                    if (layout != null) {
518                            layoutGroupId = layout.getGroupId();
519                    }
520    
521                    long plid = LayoutServiceUtil.getDefaultPlid(
522                            layoutGroupId, scopeGroupId, false, portletId);
523    
524                    if (plid == 0) {
525                            plid = LayoutServiceUtil.getDefaultPlid(
526                                    layoutGroupId, scopeGroupId, true, portletId);
527                    }
528    
529                    if (plid == 0) {
530                            if (layout != null) {
531                                    plid = layout.getPlid();
532                            }
533                    }
534    
535                    PortletURL portletURL = PortletURLFactoryUtil.create(
536                            request, portletId, plid, PortletRequest.RENDER_PHASE);
537    
538                    portletURL.setPortletMode(PortletMode.VIEW);
539                    portletURL.setWindowState(WindowState.MAXIMIZED);
540    
541                    return portletURL;
542            }
543    
544            private final boolean _enabled;
545    
546    }