1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.rest

File XWikiResource.java

 

Coverage histogram

../../../img/srcFileCovDistChart7.png
64% of files have more coverage

Code metrics

22
47
10
2
321
156
27
0.57
4.7
5
2.7

Classes

Class Line # Actions
XWikiResource 62 43 0% 24 24
0.666666766.7%
XWikiResource.DocumentInfo 112 4 0% 3 0
1.0100%
 

Contributing tests

No tests hitting this source file were found.

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.rest;
21   
22    import java.util.ArrayList;
23    import java.util.List;
24    import java.util.Locale;
25   
26    import javax.inject.Inject;
27    import javax.inject.Named;
28    import javax.inject.Provider;
29    import javax.ws.rs.GET;
30    import javax.ws.rs.Path;
31    import javax.ws.rs.Produces;
32    import javax.ws.rs.WebApplicationException;
33    import javax.ws.rs.core.Context;
34    import javax.ws.rs.core.Response.Status;
35    import javax.ws.rs.core.UriInfo;
36   
37    import org.slf4j.Logger;
38    import org.xwiki.component.annotation.InstantiationStrategy;
39    import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
40    import org.xwiki.component.manager.ComponentManager;
41    import org.xwiki.component.phase.Initializable;
42    import org.xwiki.component.phase.InitializationException;
43    import org.xwiki.localization.LocaleUtils;
44    import org.xwiki.model.reference.DocumentReference;
45    import org.xwiki.model.reference.SpaceReference;
46    import org.xwiki.query.QueryManager;
47    import org.xwiki.rest.internal.Utils;
48    import org.xwiki.rest.model.jaxb.ObjectFactory;
49   
50    import com.xpn.xwiki.XWikiContext;
51    import com.xpn.xwiki.XWikiException;
52    import com.xpn.xwiki.api.Document;
53    import com.xpn.xwiki.doc.XWikiDocument;
54   
55    /**
56    * Base class for all XWiki-related JAX-RS resources. This class provides to subclasses a set of protected fields to
57    * access the XWiki API and a method for retrieving documents in their different incarnations.
58    *
59    * @version $Id: f387b4cb7f0aace3bb5c7528600b02ec5cbeeff4 $
60    */
61    @InstantiationStrategy(ComponentInstantiationStrategy.PER_LOOKUP)
 
62    public class XWikiResource implements XWikiRestComponent, Initializable
63    {
64    /**
65    * The actual URI information about the JAX-RS resource being called. This variable is useful when generating links
66    * to other resources in representations.
67    */
68    @Context
69    protected UriInfo uriInfo;
70   
71    /**
72    * The logger to be used to output log messages.
73    *
74    * @deprecated since 7.3M1, use {@link #slf4Jlogger} instead
75    */
76    @Deprecated
77    protected java.util.logging.Logger logger;
78   
79    /**
80    * The logger to be used to output log messages.
81    *
82    * @since 7.4.5
83    * @since 8.3C1
84    */
85    @Inject
86    protected Logger slf4Jlogger;
87   
88    /**
89    * The object factory for model objects to be used when creating representations.
90    */
91    protected ObjectFactory objectFactory;
92   
93    /**
94    * The XWiki component manager that is used to lookup XWiki components and context.
95    */
96    @Inject
97    @Named("context")
98    protected ComponentManager componentManager;
99   
100    @Inject
101    protected Provider<XWikiContext> xcontextProvider;
102   
103    /**
104    * The query manager to be used to perform low-level queries for retrieving information about wiki content.
105    */
106    @Inject
107    protected QueryManager queryManager;
108   
109    /**
110    * A wrapper class for returning an XWiki document enriched with information about its status.
111    */
 
112    protected static class DocumentInfo
113    {
114    /**
115    * The target XWiki document.
116    */
117    private Document document;
118   
119    /**
120    * A boolean variable stating if the XWiki document existed already of it is being created. This variable is
121    * used when building responses in order to understand if a created or modified status code should be sent.
122    */
123    private boolean created;
124   
 
125  667 toggle public DocumentInfo(Document document, boolean created)
126    {
127  667 this.document = document;
128  667 this.created = created;
129    }
130   
 
131  667 toggle public Document getDocument()
132    {
133  667 return document;
134    }
135   
 
136  185 toggle public boolean isCreated()
137    {
138  185 return created;
139    }
140    }
141   
142    /**
143    * Resource initialization.
144    */
 
145  1571 toggle @Override
146    public void initialize() throws InitializationException
147    {
148  1571 logger = java.util.logging.Logger.getLogger(this.getClass().getName());
149   
150  1571 objectFactory = new ObjectFactory();
151   
152  1571 this.slf4Jlogger.trace("Resource {} initialized. Serving user: '{}'\n", getClass().getName(),
153    Utils.getXWikiUser(componentManager));
154    }
155   
156    /**
157    * @param spaceSegments the space segments of the URL
158    * @return the list of parent spaces
159    * @throws XWikiRestException if the URL is malformed
160    */
 
161  974 toggle public List<String> parseSpaceSegments(String spaceSegments) throws XWikiRestException
162    {
163    // The URL format is: "spaces/A/spaces/B/spaces/C" to actually point to the space "A.B.C".
164  974 List<String> spaces = new ArrayList<>();
165    // We actually don't get the first "spaces/" segment so we start from the first space
166  974 int i = 1;
167  974 for (String space : spaceSegments.split("/")) {
168  1398 if (i % 2 == 0) {
169    // Every 2 segments, we should have "spaces". If not, the URL is malformed
170  212 if (!"spaces".equals(space)) {
171  0 throw new XWikiRestException("Malformed URL: the spaces section is invalid.");
172    }
173    } else {
174  1186 spaces.add(space);
175    }
176  1398 i++;
177    }
178  974 if (spaces.isEmpty()) {
179  0 throw new XWikiRestException("Malformed URL: the spaces section is empty.");
180    }
181  974 return spaces;
182    }
183   
184    /**
185    * @param spaceSegments the space segments of the URL
186    * @param wikiName the name of the wiki
187    * @return the space reference
188    * @throws XWikiRestException if the URL is malformed
189    */
 
190  0 toggle public SpaceReference getSpaceReference(String spaceSegments, String wikiName) throws XWikiRestException
191    {
192  0 return Utils.getSpaceReference(parseSpaceSegments(spaceSegments), wikiName);
193    }
194   
195    /**
196    * Retrieve a document. This method never returns null. If something goes wrong with respect to some precondition an
197    * exception is thrown.
198    *
199    * @param wikiName The wiki name. Cannot be null.
200    * @param spaceName The space name. Cannot be null.
201    * @param pageName The page name. Cannot be null.
202    * @param language The language. Null for the default language.
203    * @param version The version. Null for the latest version.
204    * @param failIfDoesntExist True if an exception should be raised whenever the page doesn't exist.
205    * @param failIfLocked True if an exception should be raised whenever the page is locked.
206    * @return A DocumentInfo structure containing the actual document and additional information about it.
207    * @throws IllegalArgumentException If a parameter has an incorrect value (e.g. null)
208    * @throws WebApplicationException NOT_FOUND if failIfDoesntExist is true and the page doesn't exist.
209    * @throws XWikiRestException if the URL is malformed PRECONDITION_FAILED if failIfLocked is true and the document
210    * is locked.
211    */
 
212  896 toggle public DocumentInfo getDocumentInfo(String wikiName, String spaceName, String pageName, String language,
213    String version, boolean failIfDoesntExist, boolean failIfLocked) throws XWikiException, XWikiRestException
214    {
215  896 return getDocumentInfo(wikiName, parseSpaceSegments(spaceName), pageName, language, version, failIfDoesntExist,
216    failIfLocked);
217    }
218   
219    /**
220    * Retrieve a document. This method never returns null. If something goes wrong with respect to some precondition an
221    * exception is thrown.
222    *
223    * @param wikiName The wiki name. Cannot be null.
224    * @param spaces The space hierarchy. Cannot be null.
225    * @param pageName The page name. Cannot be null.
226    * @param localeString The language. Null for the default language.
227    * @param version The version. Null for the latest version.
228    * @param failIfDoesntExist True if an exception should be raised whenever the page doesn't exist.
229    * @param failIfLocked True if an exception should be raised whenever the page is locked.
230    * @return A DocumentInfo structure containing the actual document and additional information about it.
231    * @throws IllegalArgumentException If a parameter has an incorrect value (e.g. null)
232    * @throws WebApplicationException NOT_FOUND if failIfDoesntExist is true and the page doesn't exist.
233    * PRECONDITION_FAILED if failIfLocked is true and the document is locked.
234    */
 
235  918 toggle public DocumentInfo getDocumentInfo(String wikiName, List<String> spaces, String pageName, String localeString,
236    String version, boolean failIfDoesntExist, boolean failIfLocked) throws XWikiException
237    {
238  918 if ((wikiName == null) || (spaces == null || spaces.isEmpty()) || (pageName == null)) {
239  0 throw new IllegalArgumentException(
240    String.format("wikiName, spaceName and pageName must all be not null. Current values: (%s:%s.%s)",
241    wikiName, spaces, pageName));
242    }
243   
244    // If the language of the translated document is not the one we requested, then the requested translation
245    // doesn't exist. new translated document by hand.
246    // TODO: Ideally this method should take a Locale as input and not a String
247  918 Locale locale;
248  918 if (localeString != null) {
249  14 try {
250  14 locale = LocaleUtils.toLocale(localeString);
251    } catch (Exception e) {
252    // Language is invalid, we consider that the translation has not been found.
253  1 throw new WebApplicationException(Status.NOT_FOUND);
254    }
255    } else {
256  904 locale = null;
257    }
258   
259    // Create document reference
260  917 DocumentReference reference = new DocumentReference(wikiName, spaces, pageName, locale);
261   
262    // Get document
263  917 Document doc = Utils.getXWikiApi(componentManager).getDocument(reference);
264   
265    // If doc is null, we don't have the rights to access the document
266  917 if (doc == null) {
267  0 throw new WebApplicationException(Status.UNAUTHORIZED);
268    }
269   
270  917 if (failIfDoesntExist && doc.isNew()) {
271  250 throw new WebApplicationException(Status.NOT_FOUND);
272    }
273   
274    // Get a specific version if requested to
275  667 if (version != null) {
276  21 doc = doc.getDocumentRevision(version);
277    }
278   
279    // Check if the doc is locked.
280  667 if (failIfLocked && doc.getLocked()) {
281  0 throw new WebApplicationException(Status.PRECONDITION_FAILED);
282    }
283   
284  667 return new DocumentInfo(doc, doc.isNew());
285    }
286   
287    /**
288    * A special GET method that produces the ad-hoc "uritemplate" media type used for retrieving the URI template
289    * associated to a resource. This is an auxiliary method that is used for documenting the REST API.
290    *
291    * @return the URI template string associated to the requested resource
292    */
 
293  0 toggle @GET
294    @Produces("uritemplate")
295    public String getUriTemplate()
296    {
297  0 if (this.getClass().getAnnotation(Path.class) != null) {
298  0 return this.getClass().getAnnotation(Path.class).value();
299    }
300   
301  0 Class<?>[] interfaces = this.getClass().getInterfaces();
302   
303  0 for (Class<?> i : interfaces) {
304  0 if (i.getAnnotation(Path.class) != null) {
305  0 return i.getAnnotation(Path.class).value();
306    }
307    }
308   
309  0 return null;
310    }
311   
312    /**
313    * Retrieve the XWiki context from the current execution context.
314    *
315    * @return the XWiki context
316    */
 
317  403 toggle protected XWikiContext getXWikiContext()
318    {
319  403 return this.xcontextProvider.get();
320    }
321    }