1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.wysiwyg.server.internal.wiki

File AbstractWikiService.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart1.png
82% of files have more coverage

Code metrics

4
64
13
1
292
190
20
0.31
4.92
13
1.54

Classes

Class Line # Actions
AbstractWikiService 59 64 0% 20 73
0.098765439.9%
 

Contributing tests

This file is covered by 2 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.wysiwyg.server.internal.wiki;
21   
22    import java.util.ArrayList;
23    import java.util.Collections;
24    import java.util.List;
25   
26    import javax.inject.Inject;
27    import javax.inject.Named;
28    import javax.inject.Provider;
29   
30    import org.apache.commons.lang3.StringUtils;
31    import org.slf4j.Logger;
32    import org.xwiki.bridge.DocumentAccessBridge;
33    import org.xwiki.csrf.CSRFToken;
34    import org.xwiki.gwt.wysiwyg.client.wiki.Attachment;
35    import org.xwiki.gwt.wysiwyg.client.wiki.EntityConfig;
36    import org.xwiki.gwt.wysiwyg.client.wiki.ResourceReference;
37    import org.xwiki.gwt.wysiwyg.client.wiki.WikiPage;
38    import org.xwiki.gwt.wysiwyg.client.wiki.WikiPageReference;
39    import org.xwiki.gwt.wysiwyg.client.wiki.WikiService;
40    import org.xwiki.model.reference.AttachmentReference;
41    import org.xwiki.model.reference.DocumentReference;
42    import org.xwiki.model.reference.SpaceReference;
43    import org.xwiki.model.reference.SpaceReferenceResolver;
44    import org.xwiki.model.reference.WikiReference;
45    import org.xwiki.query.Query;
46    import org.xwiki.query.QueryException;
47    import org.xwiki.query.QueryFilter;
48    import org.xwiki.query.QueryManager;
49    import org.xwiki.wiki.descriptor.WikiDescriptorManager;
50    import org.xwiki.wysiwyg.server.wiki.EntityReferenceConverter;
51    import org.xwiki.wysiwyg.server.wiki.LinkService;
52   
53    /**
54    * Put here only the methods that can be implemented without depending on the old XWiki core.
55    *
56    * @version $Id: 0b8172e9a850f27cd23b90df50ae3164d8729f5c $
57    * @since 3.2
58    */
 
59    public abstract class AbstractWikiService implements WikiService
60    {
61    /**
62    * Logger.
63    */
64    @Inject
65    protected Logger logger;
66   
67    /**
68    * The object used to convert between client and server entity reference.
69    */
70    @Inject
71    protected EntityReferenceConverter entityReferenceConverter;
72   
73    /**
74    * The component used to create queries.
75    */
76    @Inject
77    private QueryManager queryManager;
78   
79    /**
80    * Provides the query filter used to filter hidden documents. We need to get the filter through a provider because
81    * it uses a per-lookup instantiation strategy.
82    */
83    @Inject
84    @Named("hidden")
85    private Provider<QueryFilter> hiddenDocumentsQueryFilterProvider;
86   
87    /**
88    * The service used to create links.
89    */
90    @Inject
91    private LinkService linkService;
92   
93    /**
94    * The component used to access documents. This is temporary till XWiki model is moved into components.
95    */
96    @Inject
97    private DocumentAccessBridge documentAccessBridge;
98   
99    /**
100    * The component that protects us against cross site request forgery by using a secret token validation mechanism.
101    * The secret token is added to the query string of the upload URL and then checked in the upload action when files
102    * are uploaded.
103    */
104    @Inject
105    private CSRFToken csrf;
106   
107    @Inject
108    private SpaceReferenceResolver<String> spaceResolver;
109   
110    @Inject
111    private WikiDescriptorManager wikiDescriptorManager;
112   
 
113  0 toggle @Override
114    public Boolean isMultiWiki()
115    {
116  0 return true;
117    }
118   
 
119  0 toggle @Override
120    public List<String> getSpaceNames(String wikiName)
121    {
122  0 try {
123  0 return queryManager.getNamedQuery("getSpaces").setWiki(wikiName)
124    .addFilter(hiddenDocumentsQueryFilterProvider.get()).execute();
125    } catch (QueryException e) {
126  0 logger.error("Failed to get the list of spaces.", e);
127  0 return Collections.emptyList();
128    }
129    }
130   
 
131  0 toggle @Override
132    public List<String> getPageNames(String wikiName, String spaceName)
133    {
134  0 String statement =
135    "select distinct doc.space, doc.name from XWikiDocument as doc where doc.space = :space "
136    + "order by doc.space, doc.name";
137  0 Query query = createHQLQuery(statement);
138  0 query.setWiki(wikiName).bindValue("space", spaceName);
139  0 List<String> pagesNames = new ArrayList<String>();
140  0 for (DocumentReference documentReference : searchDocumentReferences(query)) {
141  0 pagesNames.add(documentReference.getName());
142    }
143  0 return pagesNames;
144    }
145   
 
146  0 toggle @Override
147    public List<WikiPage> getRecentlyModifiedPages(String wikiName, int offset, int limit)
148    {
149  0 String statement =
150    "select distinct doc.space, doc.name, doc.date from XWikiDocument as doc where doc.author = :author "
151    + "order by doc.date desc, doc.space, doc.name";
152  0 Query query = createHQLQuery(statement);
153  0 query.setWiki(wikiName).setOffset(offset).setLimit(limit);
154  0 query.bindValue("author", getCurrentUserRelativeTo(wikiName));
155  0 return getWikiPages(searchDocumentReferences(query));
156    }
157   
158    /**
159    * @param wikiName the name of a wiki
160    * @return the name of the current user, relative to the specified wiki
161    */
162    protected abstract String getCurrentUserRelativeTo(String wikiName);
163   
 
164  0 toggle @Override
165    public List<WikiPage> getMatchingPages(String wikiName, String keyword, int offset, int limit)
166    {
167  0 StringBuilder statement = new StringBuilder();
168  0 statement.append("select distinct doc.space, doc.name from XWikiDocument as doc where ");
169  0 statement.append("(lower(doc.title) like '%'||:keyword||'%' or lower(doc.fullName) like '%'||:keyword||'%')");
170  0 statement.append(" order by doc.space, doc.name");
171   
172  0 Query query = createHQLQuery(statement.toString());
173  0 query.setWiki(wikiName).setOffset(offset).setLimit(limit);
174  0 query.bindValue("keyword", keyword.toLowerCase());
175   
176  0 return getWikiPages(searchDocumentReferences(query));
177    }
178   
179    /**
180    * Creates a new HQL query. Converts {@link QueryException} to a {@link RuntimeException}.
181    *
182    * @param statement the query statement
183    * @return the created query
184    */
 
185  0 toggle private Query createHQLQuery(String statement)
186    {
187  0 try {
188  0 return queryManager.createQuery(statement, Query.HQL).addFilter(hiddenDocumentsQueryFilterProvider.get());
189    } catch (QueryException e) {
190  0 throw new RuntimeException(e);
191    }
192    }
193   
194    /**
195    * Helper function to create a list of {@link WikiPage}s from a list of document references.
196    *
197    * @param documentReferences a list of document references
198    * @return the list of {@link WikiPage}s corresponding to the given document references
199    */
200    protected abstract List<WikiPage> getWikiPages(List<DocumentReference> documentReferences);
201   
202    /**
203    * Executes the given query and converts the result to a list of document references. The first two columns in each
204    * result row must be the document space and name respectively.
205    *
206    * @param query the query to be executed
207    * @return the list of document references matching the result of executing the given query
208    */
 
209  0 toggle private List<DocumentReference> searchDocumentReferences(Query query)
210    {
211  0 try {
212  0 WikiReference wikiReference = new WikiReference(query.getWiki());
213  0 List<DocumentReference> documentReferences = new ArrayList<DocumentReference>();
214  0 List<Object[]> results = query.execute();
215  0 for (Object[] result : results) {
216  0 SpaceReference spaceReference = this.spaceResolver.resolve((String) result[0], wikiReference);
217  0 documentReferences.add(new DocumentReference((String) result[1], spaceReference));
218    }
219  0 return documentReferences;
220    } catch (QueryException e) {
221  0 throw new RuntimeException(e);
222    }
223    }
224   
 
225  0 toggle @Override
226    public EntityConfig getEntityConfig(org.xwiki.gwt.wysiwyg.client.wiki.EntityReference origin,
227    ResourceReference destination)
228    {
229  0 return linkService.getEntityConfig(origin, destination);
230    }
231   
 
232  0 toggle @Override
233    public ResourceReference parseLinkReference(String linkReference,
234    org.xwiki.gwt.wysiwyg.client.wiki.EntityReference baseReference)
235    {
236  0 return linkService.parseLinkReference(linkReference, baseReference);
237    }
238   
 
239  0 toggle @Override
240    public Attachment getAttachment(org.xwiki.gwt.wysiwyg.client.wiki.AttachmentReference clientAttachmentReference)
241    {
242  0 AttachmentReference attachmentReference = entityReferenceConverter.convert(clientAttachmentReference);
243  0 try {
244  0 if (StringUtils.isBlank(documentAccessBridge.getAttachmentVersion(attachmentReference))) {
245  0 logger.warn("Failed to get attachment: [{}] not found.", attachmentReference.getName());
246  0 return null;
247    }
248    } catch (Exception e) {
249  0 logger.error("Failed to get attachment: there was a problem with getting the document on the server.", e);
250  0 return null;
251    }
252   
253  0 Attachment attach = new Attachment();
254  0 attach.setReference(clientAttachmentReference.getEntityReference());
255  0 attach.setUrl(documentAccessBridge.getAttachmentURL(attachmentReference, false));
256  0 return attach;
257    }
258   
 
259  0 toggle @Override
260    public List<Attachment> getImageAttachments(WikiPageReference reference)
261    {
262  0 List<Attachment> imageAttachments = new ArrayList<Attachment>();
263  0 List<Attachment> allAttachments = getAttachments(reference);
264  0 for (Attachment attachment : allAttachments) {
265  0 if (attachment.getMimeType().startsWith("image/")) {
266  0 imageAttachments.add(attachment);
267    }
268    }
269  0 return imageAttachments;
270    }
271   
 
272  1 toggle @Override
273    public String getUploadURL(WikiPageReference reference)
274    {
275  1 String queryString = "form_token=" + csrf.getToken();
276  1 return documentAccessBridge.getDocumentURL(entityReferenceConverter.convert(reference), "upload", queryString,
277    null);
278    }
279   
 
280  1 toggle @Override
281    public List<String> getVirtualWikiNames()
282    {
283  1 try {
284  1 List<String> wikis = new ArrayList<String>(this.wikiDescriptorManager.getAllIds());
285  1 Collections.sort(wikis);
286  1 return wikis;
287    } catch (Exception e) {
288  0 this.logger.error("Failed to retrieve the list of wikis.", e);
289  0 return Collections.emptyList();
290    }
291    }
292    }