001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.integration;
007
008import static java.lang.Integer.MAX_VALUE;
009import static javax.ws.rs.core.HttpHeaders.CONTENT_TYPE;
010import static javax.ws.rs.core.HttpHeaders.LINK;
011import static org.apache.http.HttpStatus.SC_BAD_REQUEST;
012import static org.apache.http.HttpStatus.SC_CONFLICT;
013import static org.apache.http.HttpStatus.SC_CREATED;
014import static org.apache.http.HttpStatus.SC_NO_CONTENT;
015import static org.apache.http.HttpStatus.SC_OK;
016import static org.fcrepo.kernel.api.RdfLexicon.CONSTRAINED_BY;
017import static org.junit.Assert.assertEquals;
018
019import java.io.IOException;
020import java.net.URI;
021import java.util.Objects;
022
023import com.google.common.base.Strings;
024import org.apache.http.HttpResponse;
025import org.apache.http.auth.AuthScope;
026import org.apache.http.client.CredentialsProvider;
027import org.apache.http.client.HttpClient;
028import org.apache.http.client.methods.HttpGet;
029import org.apache.http.client.methods.HttpPost;
030import org.apache.http.client.methods.HttpPut;
031import org.apache.http.client.methods.HttpUriRequest;
032import org.apache.http.entity.StringEntity;
033import org.apache.http.impl.client.HttpClientBuilder;
034import org.apache.http.util.EntityUtils;
035import org.junit.Before;
036import org.junit.Test;
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
041
042import javax.ws.rs.core.Link;
043
044/**
045 * <p>SanityCheckIT class.</p>
046 *
047 * @author fasseg
048 */
049public class SanityCheckIT {
050
051    /**
052     * The server port of the application, set as system property by
053     * maven-failsafe-plugin.
054     */
055    private static final String SERVER_PORT = Objects.requireNonNullElse(
056            Strings.emptyToNull(System.getProperty("fcrepo.dynamic.test.port")), "8080");
057
058    /**
059    * The context path of the application (including the leading "/"), set as
060    * system property by maven-failsafe-plugin.
061    */
062    private static final String CONTEXT_PATH = System.getProperty("fcrepo.test.context.path");
063
064    private Logger logger;
065
066    @Before
067    public void setLogger() {
068        logger = LoggerFactory.getLogger(this.getClass());
069    }
070
071    private static final String HOSTNAME = "localhost";
072
073    private static final String serverAddress = "http://" + HOSTNAME + ":" +
074            SERVER_PORT + CONTEXT_PATH + (CONTEXT_PATH.endsWith("/") ? "" : "/") + "rest";
075
076    private static final HttpClient client;
077
078    static {
079        final CredentialsProvider creds = new DefaultCredentialsProvider();
080        creds.setCredentials(AuthScope.ANY, AbstractResourceIT.FEDORA_ADMIN_CREDENTIALS);
081        client =
082                HttpClientBuilder.create().setMaxConnPerRoute(MAX_VALUE)
083                        .setMaxConnTotal(MAX_VALUE).setDefaultCredentialsProvider(creds).build();
084    }
085
086    @Test
087    public void doASanityCheck() throws IOException {
088        executeAndVerify(new HttpGet(serverAddress), SC_OK);
089    }
090
091    private HttpResponse executeAndVerify(final HttpUriRequest method, final int statusCode) throws IOException {
092        logger.debug("Executing: " + method.getMethod() + " to " + method.getURI());
093        final HttpResponse response = client.execute(method);
094
095        assertEquals(statusCode, response.getStatusLine().getStatusCode());
096        return response;
097    }
098
099    @Test
100    public void testConstraintLink() throws Exception {
101        // Create a resource
102        final HttpPost post = new HttpPost(serverAddress);
103        final HttpResponse postResponse = executeAndVerify(post, SC_CREATED);
104
105        final String location = postResponse.getFirstHeader("Location").getValue();
106        logger.debug("new resource location: {}", location);
107
108        // GET the new resource
109        final HttpGet get = new HttpGet(location);
110        final HttpResponse getResponse = executeAndVerify(get, SC_OK);
111
112        final String body = EntityUtils.toString(getResponse.getEntity());
113        logger.debug("new resource body: {}", body);
114
115        // PUT the exact body back to the new resource... successfully
116        final HttpPut put = new HttpPut(location);
117        put.setEntity(new StringEntity(body));
118        put.setHeader(CONTENT_TYPE, "text/turtle");
119        put.setHeader("Prefer", "handling=lenient");
120        executeAndVerify(put, SC_NO_CONTENT);
121
122        // Update a server managed property in the resource body... not allowed!
123        final String body2 = body.replaceFirst("fedora:created \"2\\d\\d\\d", "fedora:created \"1999");
124
125        // PUT the erroneous body back to the new resource... unsuccessfully
126        final HttpPut put2 = new HttpPut(location);
127        put2.setEntity(new StringEntity(body2));
128        put2.setHeader(CONTENT_TYPE, "text/turtle");
129        final HttpResponse put2Response = executeAndVerify(put2, SC_CONFLICT);
130
131        // Verify the returned LINK header
132        final String linkHeader = put2Response.getFirstHeader(LINK).getValue();
133        final Link link = Link.valueOf(linkHeader);
134        logger.debug("constraint linkHeader: {}", linkHeader);
135
136        // Verify the LINK rel
137        final String linkRel = link.getRel();
138        assertEquals(CONSTRAINED_BY.getURI(), linkRel);
139
140        // Verify the LINK URI by fetching it
141        final URI linkURI = link.getUri();
142        logger.debug("constraint linkURI: {}", linkURI);
143
144        final HttpGet getLink = new HttpGet(linkURI);
145        executeAndVerify(getLink, SC_OK);
146    }
147
148    @Test
149    public void testCannotCreateResourceConstraintLink() throws Exception {
150        // Create a ldp:Resource resource, this should fail
151        final HttpPost post = new HttpPost(serverAddress);
152        post.setHeader(LINK,"<http://www.w3.org/ns/ldp#Resource>; rel=\"type\"");
153        final HttpResponse postResponse = executeAndVerify(post, SC_BAD_REQUEST);
154
155        // Verify the returned LINK header
156        final String linkHeader = postResponse.getFirstHeader(LINK).getValue();
157        final Link link = Link.valueOf(linkHeader);
158        logger.debug("constraint linkHeader: {}", linkHeader);
159
160        // Verify the LINK rel
161        final String linkRel = link.getRel();
162        assertEquals(CONSTRAINED_BY.getURI(), linkRel);
163
164        // Verify the LINK URI by fetching it
165        final URI linkURI = link.getUri();
166        logger.debug("constraint linkURI: {}", linkURI);
167
168        final HttpGet getLink = new HttpGet(linkURI);
169        executeAndVerify(getLink, SC_OK);
170    }
171
172    @Test
173    public void testUnicodeCharsAllowed() throws Exception {
174        final var id = "ÅŤéșţ!";
175        final var url = serverAddress + "/" + id;
176
177        final HttpPut put = new HttpPut(url);
178        put.setEntity(new StringEntity("testing"));
179        put.setHeader(CONTENT_TYPE, "text/plain");
180        executeAndVerify(put, SC_CREATED);
181
182        executeAndVerify(new HttpGet(url), SC_OK);
183    }
184}