001/*
002 * (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     dmetzler
018 */
019package org.nuxeo.ecm.restapi.test;
020
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertTrue;
023
024import java.io.IOException;
025import java.io.InputStream;
026import java.util.ArrayList;
027import java.util.Iterator;
028import java.util.List;
029import java.util.Map;
030
031import javax.inject.Inject;
032import javax.ws.rs.core.MediaType;
033import javax.ws.rs.core.MultivaluedMap;
034import javax.ws.rs.core.Response;
035
036import org.codehaus.jackson.JsonNode;
037import org.codehaus.jackson.JsonProcessingException;
038import org.codehaus.jackson.map.ObjectMapper;
039import org.junit.Before;
040import org.nuxeo.ecm.core.api.CoreSession;
041import org.nuxeo.ecm.core.api.DocumentModel;
042import org.nuxeo.runtime.transaction.TransactionHelper;
043
044import com.sun.jersey.api.client.Client;
045import com.sun.jersey.api.client.ClientResponse;
046import com.sun.jersey.api.client.WebResource;
047import com.sun.jersey.api.client.WebResource.Builder;
048import com.sun.jersey.api.client.config.ClientConfig;
049import com.sun.jersey.api.client.config.DefaultClientConfig;
050import com.sun.jersey.api.client.filter.HTTPBasicAuthFilter;
051import com.sun.jersey.multipart.MultiPart;
052import com.sun.jersey.multipart.impl.MultiPartWriter;
053
054/**
055 * @since 5.7.2
056 */
057public class BaseTest {
058
059    private static final Integer TIMEOUT = Integer.valueOf(1000 * 60 * 5); // 5min
060
061    protected static enum RequestType {
062        GET, POST, DELETE, PUT, POSTREQUEST, GETES
063    }
064
065    protected ObjectMapper mapper;
066
067    protected Client client;
068
069    protected WebResource service;
070
071    @Before
072    public void doBefore() throws Exception {
073        service = getServiceFor("Administrator", "Administrator");
074
075        mapper = new ObjectMapper();
076
077    }
078
079    /**
080     * @param user
081     * @param password
082     * @return
083     * @since 5.7.3
084     */
085    protected WebResource getServiceFor(String user, String password) {
086        ClientConfig config = new DefaultClientConfig();
087        config.getClasses().add(MultiPartWriter.class);
088        client = Client.create(config);
089        client.setConnectTimeout(TIMEOUT);
090        client.setReadTimeout(TIMEOUT);
091        client.addFilter(new HTTPBasicAuthFilter(user, password));
092
093        return client.resource("http://localhost:18090/api/v1/");
094    }
095
096    @Inject
097    public CoreSession session;
098
099    protected ClientResponse getResponse(RequestType requestType, String path) {
100        return getResponse(requestType, path, null, null, null, null);
101    }
102
103    protected ClientResponse getResponse(RequestType requestType, String path, Map<String, String> headers) {
104        return getResponse(requestType, path, null, null, null, headers);
105    }
106
107    protected ClientResponse getResponse(RequestType requestType, String path, MultiPart mp) {
108        return getResponse(requestType, path, null, null, mp, null);
109    }
110
111    protected ClientResponse getResponse(RequestType requestType, String path, MultiPart mp, Map<String, String> headers) {
112        return getResponse(requestType, path, null, null, mp, headers);
113    }
114
115    protected ClientResponse getResponse(RequestType requestType, String path,
116            MultivaluedMap<String, String> queryParams) {
117        return getResponse(requestType, path, null, queryParams, null, null);
118    }
119
120    protected ClientResponse getResponse(RequestType requestType, String path, String data) {
121        return getResponse(requestType, path, data, null, null, null);
122    }
123
124    protected ClientResponse getResponse(RequestType requestType, String path, String data, Map<String, String> headers) {
125        return getResponse(requestType, path, data, null, null, headers);
126    }
127
128    protected ClientResponse getResponse(RequestType requestType, String path, String data,
129            MultivaluedMap<String, String> queryParams, MultiPart mp, Map<String, String> headers) {
130        WebResource wr = service.path(path);
131
132        if (queryParams != null && !queryParams.isEmpty()) {
133            wr = wr.queryParams(queryParams);
134        }
135        Builder builder;
136        if (requestType == RequestType.GETES) {
137            builder = wr.accept("application/json+esentity");
138        } else {
139            builder = wr.accept(MediaType.APPLICATION_JSON).header("X-NXDocumentProperties", "dublincore");
140        }
141        if (mp != null) {
142            builder = wr.type(MediaType.MULTIPART_FORM_DATA_TYPE);
143        }
144
145        if (headers == null || !(headers.containsKey("Content-Type"))) {
146            if (requestType == RequestType.POSTREQUEST) {
147                builder.header("Content-Type", "application/json+nxrequest");
148            } else {
149                builder.header("Content-Type", "application/json+nxentity");
150            }
151        }
152
153        // Adding some headers if needed
154        if (headers != null && !headers.isEmpty()) {
155            for (String headerKey : headers.keySet()) {
156                builder.header(headerKey, headers.get(headerKey));
157            }
158        }
159        switch (requestType) {
160        case GET:
161        case GETES:
162            return builder.get(ClientResponse.class);
163        case POST:
164        case POSTREQUEST:
165            if (mp != null) {
166                return builder.post(ClientResponse.class, mp);
167            } else {
168                return builder.post(ClientResponse.class, data);
169            }
170        case PUT:
171            if (mp != null) {
172                return builder.put(ClientResponse.class, mp);
173            } else {
174                return builder.put(ClientResponse.class, data);
175            }
176        case DELETE:
177            return builder.delete(ClientResponse.class, data);
178        default:
179            throw new RuntimeException();
180        }
181    }
182
183    protected JsonNode getResponseAsJson(RequestType responseType, String url) throws IOException,
184            JsonProcessingException {
185        return getResponseAsJson(responseType, url, null);
186    }
187
188    /**
189     * @param get
190     * @param string
191     * @param queryParamsForPage
192     * @return
193     * @throws IOException
194     * @throws JsonProcessingException
195     * @since 5.8
196     */
197    protected JsonNode getResponseAsJson(RequestType responseType, String url,
198            MultivaluedMap<String, String> queryParams) throws JsonProcessingException, IOException {
199        ClientResponse response = getResponse(responseType, url, queryParams);
200        assertEquals(Response.Status.OK.getStatusCode(), response.getStatus());
201        return mapper.readTree(response.getEntityInputStream());
202    }
203
204    /**
205     * Fetch session invalidations.
206     *
207     * @since 5.9.3
208     */
209    protected void fetchInvalidations() {
210        session.save();
211        if (TransactionHelper.isTransactionActiveOrMarkedRollback()) {
212            TransactionHelper.commitOrRollbackTransaction();
213            TransactionHelper.startTransaction();
214        }
215    }
216
217    protected void assertNodeEqualsDoc(JsonNode node, DocumentModel note) throws Exception {
218        assertEquals("document", node.get("entity-type").getValueAsText());
219        assertEquals(note.getPathAsString(), node.get("path").getValueAsText());
220        assertEquals(note.getId(), node.get("uid").getValueAsText());
221        assertEquals(note.getTitle(), node.get("title").getValueAsText());
222    }
223
224    protected List<JsonNode> getLogEntries(JsonNode node) {
225        assertEquals("documents", node.get("entity-type").getValueAsText());
226        assertTrue(node.get("entries").isArray());
227        List<JsonNode> result = new ArrayList<>();
228        Iterator<JsonNode> elements = node.get("entries").getElements();
229        while (elements.hasNext()) {
230            result.add(elements.next());
231        }
232        return result;
233    }
234
235    /**
236     * @since 7.1
237     */
238    protected String getErrorMessage(JsonNode node) {
239        assertEquals("exception", node.get("entity-type").getValueAsText());
240        assertTrue(node.get("message").isTextual());
241        return node.get("message").getValueAsText();
242    }
243
244    protected void assertEntityEqualsDoc(InputStream in, DocumentModel doc) throws Exception {
245
246        JsonNode node = mapper.readTree(in);
247        assertNodeEqualsDoc(node, doc);
248
249    }
250}