1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.templating.functions;
35
36 import static com.google.common.base.Preconditions.checkArgument;
37
38 import info.magnolia.cms.security.PermissionUtil;
39 import info.magnolia.context.MgnlContext;
40 import info.magnolia.jcr.util.ContentMap;
41 import info.magnolia.jcr.util.NodeTypes;
42 import info.magnolia.jcr.wrapper.I18nNodeWrapper;
43 import info.magnolia.repository.RepositoryConstants;
44
45 import java.util.ArrayList;
46 import java.util.Collection;
47 import java.util.List;
48
49 import javax.inject.Singleton;
50 import javax.jcr.Node;
51 import javax.jcr.RepositoryException;
52 import javax.jcr.Session;
53 import javax.jcr.query.Query;
54 import javax.jcr.query.QueryManager;
55 import javax.jcr.query.QueryResult;
56 import javax.jcr.query.Row;
57 import javax.jcr.query.RowIterator;
58
59 import org.apache.commons.lang3.StringUtils;
60 import org.apache.jackrabbit.JcrConstants;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101 @Singleton
102 public class SearchTemplatingFunctions {
103
104 private static final Logger log = LoggerFactory.getLogger(SearchTemplatingFunctions.class);
105
106 private static final String SEARCH_QUERY_PATTERN = "SELECT rep:excerpt() from %s WHERE jcr:path like '%s/%%' AND contains(., '%s') ORDER BY jcr:score() DESC";
107
108
109
110
111
112
113 public Collection<ContentMap> searchPages(String queryString, String startPath) throws RepositoryException {
114 return searchPages(queryString, startPath, Integer.MAX_VALUE, 0);
115 }
116
117
118
119
120
121
122 public Collection<ContentMap> searchPages(String queryString, String startPath, long limit, long offset) throws RepositoryException {
123 return searchContent(RepositoryConstants.WEBSITE, queryString, startPath, NodeTypes.Page.NAME, limit, offset);
124 }
125
126
127
128
129
130
131
132 public Collection<ContentMap> searchContent(String workspace, String queryString, String startPath, String returnItemType) throws RepositoryException {
133 return searchContent(workspace, queryString, startPath, returnItemType, Integer.MAX_VALUE, 0);
134 }
135
136
137
138
139
140
141 public Collection<ContentMap> searchContent(String workspace, String queryString, String startPath, String returnItemType, long limit, long offset) throws RepositoryException {
142
143 checkArgument(StringUtils.isNotBlank(workspace), "workspace can't be null or empty");
144 checkArgument(StringUtils.isNotBlank(queryString), "queryString can't be null or empty");
145 checkArgument(StringUtils.isNotBlank(startPath), "startPath can't be null or empty");
146 checkArgument(limit > 0, "limit was %s but it must be greater than 0", limit);
147 checkArgument(offset >= 0, "offset was %s but it must be greater than or equal to 0", offset);
148
149 List<ContentMap> result = new ArrayList<ContentMap>();
150
151 final Session jcrSession = MgnlContext.getJCRSession(workspace);
152 final QueryManager jcrQueryManager = jcrSession.getWorkspace().getQueryManager();
153
154 final Query query = jcrQueryManager.createQuery(String.format(SEARCH_QUERY_PATTERN, StringUtils.defaultIfBlank(returnItemType, JcrConstants.NT_BASE), startPath, queryString), Query.SQL);
155 query.setLimit(limit);
156 query.setOffset(offset);
157
158 log.debug("Executing query against workspace [{}] with statement [{}] and limit {} and offset {}...", workspace, query.getStatement(), limit, offset);
159 long start = System.currentTimeMillis();
160 QueryResult qr = query.execute();
161 log.debug("Query execution took {} ms", System.currentTimeMillis() - start);
162 RowIterator it = qr.getRows();
163
164 while (it.hasNext()) {
165 Row row = it.nextRow();
166 Node node = row.getNode();
167 if (PermissionUtil.isGranted(jcrSession, node.getPath(), Session.ACTION_READ)) {
168 String excerpt = hasExcerptValue(row) ? row.getValue("rep:excerpt()").getString() : "";
169 node.setProperty("excerpt", excerpt);
170 result.add(new ContentMap(new I18nNodeWrapper(node)));
171 }
172 }
173
174 return result;
175
176 }
177
178 private boolean hasExcerptValue(Row row) {
179 try {
180 row.getValue("rep:excerpt()");
181 return true;
182 } catch (RepositoryException e) {
183 }
184 return false;
185 }
186 }