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

File AbstractFormUrlEncodedAnnotationRequestReader.java

 

Coverage histogram

../../../../../../img/srcFileCovDistChart6.png
69% of files have more coverage

Code metrics

8
27
2
1
147
73
8
0.3
13.5
2
4

Classes

Class Line # Actions
AbstractFormUrlEncodedAnnotationRequestReader 51 27 0% 8 15
0.594594659.5%
 

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.annotation.rest.internal.representations;
21   
22    import java.io.IOException;
23    import java.io.InputStream;
24    import java.lang.annotation.Annotation;
25    import java.lang.reflect.Type;
26    import java.util.Map;
27   
28    import javax.servlet.http.HttpServletRequest;
29    import javax.ws.rs.WebApplicationException;
30    import javax.ws.rs.core.MediaType;
31    import javax.ws.rs.core.MultivaluedMap;
32    import javax.ws.rs.ext.MessageBodyReader;
33   
34    import org.restlet.Context;
35    import org.restlet.Request;
36    import org.restlet.data.Form;
37    import org.xwiki.annotation.rest.model.jaxb.AnnotationField;
38    import org.xwiki.annotation.rest.model.jaxb.AnnotationRequest;
39    import org.xwiki.annotation.rest.model.jaxb.ObjectFactory;
40    import org.xwiki.rest.Constants;
41    import org.xwiki.rest.XWikiRestComponent;
42   
43    /**
44    * Partial implementation of a reader from form submits requests for annotation related types, to handle generic request
45    * reader code.
46    *
47    * @param <T> the type read from the url encoded form
48    * @version $Id: 747b2592aa647e7d0d6fa683e74a6f68573c86f0 $
49    * @since 2.3M1
50    */
 
51    public abstract class AbstractFormUrlEncodedAnnotationRequestReader<T extends AnnotationRequest> implements
52    MessageBodyReader<T>, XWikiRestComponent
53    {
54    /**
55    * The parameter name for a field requested to appear in the annotations stub. <br>
56    * Note: This can get problematic if a custom field of the annotation is called the same
57    */
58    protected static final String REQUESTED_FIELD = "request_field";
59   
60    /**
61    * The prefix of the parameters of the annotations filters. <br>
62    * Note: This can get problematic if custom fields of the annotation are called the same
63    */
64    protected static final String FILTER_FIELD_PREFIX = "filter_";
65   
66    /**
67    * Helper function to provide an instance of the read object from the object factory.
68    *
69    * @param factory the object factory
70    * @return an instance of the read type T, as built by the object factory.
71    */
72    protected abstract T getReadObjectInstance(ObjectFactory factory);
73   
 
74  8 toggle @Override
75    public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType,
76    MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException,
77    WebApplicationException
78    {
79  8 ObjectFactory objectFactory = new ObjectFactory();
80  8 T annotationRequest = getReadObjectInstance(objectFactory);
81   
82  8 try {
83    // Try to parse a form from the content of this request
84    // FIXME should this method even try to read and consume the entity stream at all ?
85    // It seems it is already consumed upstream by the time this body reader is invoked.
86  8 Form form = new Form(Request.getCurrent().getEntity());
87   
88  0 if (form.getNames().size() != 0) {
89  0 for (String paramName : form.getNames()) {
90  0 for (String paramValue : form.getValuesArray(paramName)) {
91  0 saveField(annotationRequest, paramName, paramValue, objectFactory);
92    }
93    }
94    }
95    } catch (IllegalStateException e) {
96    // If the entity stream has been consumed already by a filter, Restlet will complain with an ISE
97    // Try to read data using the parameters
98  8 HttpServletRequest httpServletRequest =
99    (HttpServletRequest) Context.getCurrent().getAttributes().get(Constants.HTTP_REQUEST);
100  8 for (Object entryObj : httpServletRequest.getParameterMap().entrySet()) {
101  36 Map.Entry entry = (Map.Entry) entryObj;
102    // FIXME: this needs to be done right, it can interfere with the custom parameters names
103    // skip method & media parameters, used by REST to carry its own parameters
104  36 if ("method".equals(entry.getKey()) || "media".equals(entry.getKey())) {
105  12 continue;
106    }
107    // save all the values of this field, one by one
108  24 String[] paramValues = (String[]) entry.getValue();
109  24 for (String value : paramValues) {
110  24 saveField(annotationRequest, (String) entry.getKey(), value, objectFactory);
111    }
112    }
113    }
114   
115  8 return annotationRequest;
116    }
117   
118    /**
119    * Helper function to save a parameter in the read object. To implement in subclasses to provide type specific
120    * behaviour.
121    *
122    * @param readObject the request to fill with data
123    * @param key the key of the field
124    * @param value the value of the field
125    * @param objectFactory the objects factory to create the annotation fields
126    * @return true if the field was saved at this level, false otherwise
127    */
 
128  12 toggle protected boolean saveField(T readObject, String key, String value, ObjectFactory objectFactory)
129    {
130    // if the field is a requested field, put it in the requested fields list
131  12 if (REQUESTED_FIELD.equals(key)) {
132  0 readObject.getRequest().getFields().add(value);
133  0 return true;
134    }
135    // if the field is a filter field, direct it to the filter fields collection
136  12 if (key.startsWith(FILTER_FIELD_PREFIX)) {
137  0 AnnotationField filterField = objectFactory.createAnnotationField();
138    // put only the name of the prop to filter for, not the filter prefix too
139  0 filterField.setName(key.substring(FILTER_FIELD_PREFIX.length()));
140  0 filterField.setValue(value);
141  0 readObject.getFilter().getFields().add(filterField);
142  0 return true;
143    }
144   
145  12 return false;
146    }
147    }