() {
});
}
diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java
index 8bd5c8e1..a133ac87 100644
--- a/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java
+++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/RedirectFilter.java
@@ -20,50 +20,37 @@
*/
package org.zanata.rest.client;
+import java.io.IOException;
import java.net.URI;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.core.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.sun.jersey.api.client.ClientHandler;
-import com.sun.jersey.api.client.ClientHandlerException;
-import com.sun.jersey.api.client.ClientRequest;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.filter.ClientFilter;
/**
+ * Resteasy does not support following redirect. https://issues.jboss.org/browse/RESTEASY-1075
+ *
+ * However there is a workaround. https://github.com/teacurran/sonar-bitbucket/commit/fa978b3d7c0c98ee0bc60c908379fc42dbeae5f4
+ *
* @author Patrick Huang pahuang@redhat.com
*/
-public class RedirectFilter extends ClientFilter {
+public class RedirectFilter implements ClientResponseFilter {
private static final Logger log =
LoggerFactory.getLogger(RedirectFilter.class);
@Override
- public ClientResponse handle(ClientRequest clientRequest)
- throws ClientHandlerException {
- ClientHandler ch = getNext();
- ClientResponse resp = ch.handle(clientRequest);
-
- if (resp.getClientResponseStatus().getFamily() !=
+ public void filter(ClientRequestContext requestContext,
+ ClientResponseContext responseContext) throws IOException {
+ if (responseContext.getStatusInfo().getFamily() ==
Response.Status.Family.REDIRECTION) {
- return resp;
- } else {
- // try location only if for GET and HEAD
- String method = clientRequest.getMethod();
- if ("HEAD".equals(method) || "GET".equals(method)) {
- log.debug(
- "Server returns redirection status: {}. Try to follow it",
- resp.getClientResponseStatus());
- URI redirectTarget = resp.getLocation();
- if (redirectTarget != null) {
- clientRequest.setURI(redirectTarget);
- }
- return ch.handle(clientRequest);
- } else {
- throw new IllegalStateException(
- "Received status " + resp.getClientResponseStatus() +
- ". Check your server URL (e.g. used http instead of https)");
- }
+ URI redirectTarget = responseContext.getLocation();
+ throw new IllegalStateException(
+ String.format(
+ "Received status %s. Redirected to %s. Check your server URL (e.g. used http instead of https)",
+ responseContext.getStatusInfo(), redirectTarget));
}
}
}
diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/ResponseStatusFilter.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/ResponseStatusFilter.java
new file mode 100644
index 00000000..1b187949
--- /dev/null
+++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/ResponseStatusFilter.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016, Red Hat, Inc. and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.zanata.rest.client;
+
+import java.io.BufferedInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.net.URI;
+import javax.ws.rs.ClientErrorException;
+import javax.ws.rs.NotAuthorizedException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.RedirectionException;
+import javax.ws.rs.ServerErrorException;
+import javax.ws.rs.ServiceUnavailableException;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
+import javax.ws.rs.core.Response;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Strings;
+
+/**
+ * @author Patrick Huang pahuang@redhat.com
+ */
+public class ResponseStatusFilter implements ClientResponseFilter {
+ private static final Logger log =
+ LoggerFactory.getLogger(ResponseStatusFilter.class);
+ @Override
+ public void filter(ClientRequestContext requestContext,
+ ClientResponseContext responseContext) throws IOException {
+ int statusCode = responseContext.getStatus();
+ Response.StatusType responseStatus = responseContext.getStatusInfo();
+
+ if (isRedirect(responseStatus)) {
+ // if server returns a redirect (most likely due to http to https
+ // redirect), we don't want to bury this information in a xml
+ // marshalling exception.
+ String message =
+ "Server returned a redirect. You must change your url option or config file.";
+ // getLocation() can return null but it's acceptable
+ throw new RedirectionException(message, statusCode,
+ responseContext.getLocation());
+ } else if (statusCode >= 399) {
+ URI uri = requestContext.getUri();
+ String entity = tryGetEntity(responseContext);
+ String msg =
+ generateErrorMessage(statusCode, responseStatus, uri,
+ entity);
+
+ if (responseStatus == Response.Status.UNAUTHORIZED) {
+ throw new NotAuthorizedException("Incorrect username/password");
+ } else if (responseStatus == Response.Status.NOT_FOUND) {
+ throw new NotFoundException(msg);
+ } else if (statusCode < 500) {
+ throw new ClientErrorException(msg, statusCode);
+ } else if (responseStatus == Response.Status.SERVICE_UNAVAILABLE) {
+ throw new ServiceUnavailableException(
+ "Service is currently unavailable. " +
+ "Please check outage notification or try again later.");
+ } else {
+ if (responseStatus == Response.Status.SERVICE_UNAVAILABLE) {
+ msg = "Service is currently unavailable. " +
+ "Please check outage notification or try again later.";
+ throw new ServiceUnavailableException(msg);
+ }
+ throw new ServerErrorException(msg, statusCode);
+ }
+ }
+ }
+
+ private static boolean isRedirect(Response.StatusType statusCode) {
+ return statusCode == Response.Status.MOVED_PERMANENTLY
+ || statusCode == Response.Status.FOUND;
+ }
+
+ private static String tryGetEntity(ClientResponseContext responseContext) {
+ String entity = "";
+ if (responseContext.hasEntity()) {
+ try (BufferedInputStream bufferedIs = new BufferedInputStream(
+ responseContext.getEntityStream());
+ ByteArrayOutputStream result = new ByteArrayOutputStream()) {
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = bufferedIs.read(buffer)) != -1) {
+ result.write(buffer, 0, length);
+ }
+ entity = ":" + result.toString("UTF-8");
+
+ } catch (Exception e) {
+ log.debug("error reading input stream", e);
+ }
+ }
+ return entity;
+ }
+
+ private static String generateErrorMessage(int statusCode,
+ Response.StatusType responseStatus, URI uri, String entity) {
+ return String.format("operation to [%s] returned %d (%s):%s",
+ uri, statusCode, responseStatus, entity);
+ }
+}
diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/RestClientFactory.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/RestClientFactory.java
index b1f543ee..38b581aa 100644
--- a/zanata-rest-client/src/main/java/org/zanata/rest/client/RestClientFactory.java
+++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/RestClientFactory.java
@@ -29,26 +29,22 @@
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
-import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.core.MediaType;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
-import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
+import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.zanata.rest.MediaTypes;
import org.zanata.rest.RestConstant;
import org.zanata.rest.dto.VersionInfo;
import com.google.common.base.Throwables;
-import com.sun.jersey.api.client.Client;
-import com.sun.jersey.api.client.config.ClientConfig;
-import com.sun.jersey.api.client.config.DefaultClientConfig;
-import com.sun.jersey.client.urlconnection.HTTPSProperties;
-import com.sun.jersey.multipart.impl.MultiPartWriter;
/**
* @author Patrick Huang getResourceMeta(Set extensions) {
Client client = factory.getClient();
- WebResource webResource = getBaseServiceResource(client)
- .queryParams(ClientUtil.asMultivaluedMap(
- "ext", extensions));
- return webResource
- .get(new GenericType>() {
- });
+ WebTarget webResource = getBaseServiceResource(client);
+ if (extensions != null) {
+ webResource.queryParam("ext", extensions.toArray());
+ }
+ return webResource.request(MediaType.APPLICATION_XML_TYPE)
+ .get(new GenericType>() {});
}
- private WebResource getBaseServiceResource(Client client) {
- return client.resource(baseUri)
+ private WebTarget getBaseServiceResource(Client client) {
+ return client.target(baseUri)
.path("projects").path("p")
.path(project)
.path("iterations").path("i")
@@ -77,34 +80,32 @@ private WebResource getBaseServiceResource(Client client) {
public Resource getResource(String idNoSlash, Set extensions) {
Client client = factory.getClient();
- WebResource webResource =
+ WebTarget webResource =
getBaseServiceResource(client)
.path(idNoSlash)
- .queryParams(ClientUtil.asMultivaluedMap(
- "ext", extensions));
- return webResource.get(Resource.class);
+ .queryParam("ext", extensions.toArray());
+ return webResource.request(MediaType.APPLICATION_XML_TYPE)
+ .get(Resource.class);
}
public String putResource(String idNoSlash, Resource resource,
Set extensions, boolean copyTrans) {
Client client = factory.getClient();
- CacheResponseFilter filter = new CacheResponseFilter();
- client.addFilter(filter);
- WebResource webResource = getBaseServiceResource(client)
+ WebTarget webResource = getBaseServiceResource(client)
.path(idNoSlash)
- .queryParams(ClientUtil.asMultivaluedMap(
- "ext", extensions))
+ .queryParam("ext", extensions.toArray())
.queryParam("copyTrans", String.valueOf(copyTrans));
- webResource.put(resource);
- client.removeFilter(filter);
- return filter.getEntity(String.class);
+ Response response = webResource.request(MediaType.APPLICATION_XML_TYPE)
+ .put(Entity.entity(resource, MediaType.APPLICATION_XML_TYPE));
+ response.bufferEntity();
+ return response.readEntity(String.class);
}
public String deleteResource(String idNoSlash) {
Client client = factory.getClient();
- WebResource webResource = getBaseServiceResource(client);
- return webResource.path(idNoSlash).delete(String.class);
+ WebTarget webResource = getBaseServiceResource(client);
+ return webResource.path(idNoSlash).request().delete(String.class);
}
}
diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/StatisticsResourceClient.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/StatisticsResourceClient.java
index 28f3f3ea..c5edef77 100644
--- a/zanata-rest-client/src/main/java/org/zanata/rest/client/StatisticsResourceClient.java
+++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/StatisticsResourceClient.java
@@ -22,17 +22,13 @@
package org.zanata.rest.client;
import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
import javax.ws.rs.DefaultValue;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
import org.zanata.rest.dto.stats.ContainerTranslationStatistics;
import org.zanata.rest.dto.stats.contribution.ContributionStatistics;
import org.zanata.rest.service.StatisticsResource;
-import com.google.common.collect.Lists;
-import com.sun.jersey.api.client.WebResource;
-
-import static org.zanata.rest.client.ClientUtil.asMultivaluedMap;
/**
* @author Patrick Huang toLocaleList(String[] locales) {
- List localesList;
- if (locales == null) {
- localesList = Lists.newArrayList();
- } else {
- localesList = Lists.newArrayList(locales);
- }
- return localesList;
+ .queryParam("detail", includeDetails)
+ .queryParam("word", includeWordStats)
+ .queryParam("locale", (Object[]) locales);
+ return webResource.request(MediaType.APPLICATION_XML_TYPE)
+ .get(ContainerTranslationStatistics.class);
}
@Override
public ContainerTranslationStatistics getStatistics(String projectSlug,
String iterationSlug, String docId,
@DefaultValue("false") boolean includeWordStats, String[] locales) {
- WebResource webResource =
- factory.getClient().resource(baseUri).path("stats")
+ WebTarget webResource =
+ factory.getClient().target(baseUri).path("stats")
.path("proj")
.path(projectSlug)
.path("iter")
@@ -88,16 +74,16 @@ public ContainerTranslationStatistics getStatistics(String projectSlug,
.path("doc")
.path(docId)
.queryParam("word", String.valueOf(includeWordStats))
- .queryParams(asMultivaluedMap("locale",
- toLocaleList(locales)));
- return webResource.get(ContainerTranslationStatistics.class);
+ .queryParam("locale", (Object[]) locales);
+ return webResource.request(MediaType.APPLICATION_XML_TYPE)
+ .get(ContainerTranslationStatistics.class);
}
@Override
public ContributionStatistics getContributionStatistics(String projectSlug,
String versionSlug, String username, String dateRange, boolean includeAutomatedEntry) {
- WebResource webResource =
- factory.getClient().resource(baseUri).path("stats")
+ WebTarget webResource =
+ factory.getClient().target(baseUri).path("stats")
.path("project")
.path(projectSlug)
.path("version")
@@ -105,7 +91,8 @@ public ContributionStatistics getContributionStatistics(String projectSlug,
.path("contributor")
.path(username)
.path(dateRange)
- .queryParam("includeAutomatedEntry", String.valueOf(includeAutomatedEntry));
- return webResource.get(ContributionStatistics.class);
+ .queryParam("includeAutomatedEntry", includeAutomatedEntry);
+ return webResource.request(MediaType.APPLICATION_JSON_TYPE)
+ .get(ContributionStatistics.class);
}
}
diff --git a/zanata-rest-client/src/main/java/org/zanata/rest/client/TraceDebugFilter.java b/zanata-rest-client/src/main/java/org/zanata/rest/client/TraceDebugFilter.java
index 3ea3e3f0..a48c4ce2 100644
--- a/zanata-rest-client/src/main/java/org/zanata/rest/client/TraceDebugFilter.java
+++ b/zanata-rest-client/src/main/java/org/zanata/rest/client/TraceDebugFilter.java
@@ -21,9 +21,14 @@
package org.zanata.rest.client;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.client.ClientResponseContext;
+import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.ext.Provider;
import org.slf4j.Logger;
@@ -31,10 +36,6 @@
import org.zanata.rest.RestConstant;
import com.google.common.base.Charsets;
-import com.sun.jersey.api.client.ClientHandlerException;
-import com.sun.jersey.api.client.ClientRequest;
-import com.sun.jersey.api.client.ClientResponse;
-import com.sun.jersey.api.client.filter.ClientFilter;
/**
* Performs logging of Requests on the client side. This interceptor
@@ -46,59 +47,19 @@
*
*/
@Provider
-public class TraceDebugFilter extends ClientFilter {
+public class TraceDebugFilter implements ClientRequestFilter,
+ ClientResponseFilter {
private static final Logger log = LoggerFactory
.getLogger(TraceDebugFilter.class);
private boolean logHttp;
- @Override
- public ClientResponse handle(ClientRequest cr)
- throws ClientHandlerException {
- if (!logHttp && !log.isTraceEnabled()) {
- return getNext().handle(cr);
- }
- log(">> REST Request: " + cr.getMethod() + " => "
- + cr.getURI());
-
- // Log before sending a request
- for (String key : cr.getHeaders().keySet()) {
- String headerVal =
- cr.getHeaders().get(key).toString();
- if (key.equals(RestConstant.HEADER_API_KEY)) {
- headerVal =
- this.maskHeaderValues(
- cr.getHeaders()
- .get(key));
- }
-
- log(">> Header: " + key + " = " + headerVal);
- }
- log(">> body: " + cr.getEntity());
-
-
-
- ClientResponse response = getNext().handle(cr);
-
- // log after a response has been received
- log("<< REST Response: " + response.getStatus()
- + ":" + response.getClientResponseStatus());
- for (String key : response.getHeaders().keySet()) {
- log("<< Header: " + key + " = " +
- response.getHeaders().get(key));
- }
- response.bufferEntity();
- log(">> Body: " + getPayloadAsString(response));
- return response;
- }
-
- // this is jersey implementation specific
- private String getPayloadAsString(ClientResponse response) {
+ private String getPayloadAsString(ClientResponseContext response) {
ByteArrayInputStream entityInputStream = null;
try {
entityInputStream =
- (ByteArrayInputStream) response.getEntityInputStream();
+ (ByteArrayInputStream) response.getEntityStream();
int available = entityInputStream.available();
byte[] data = new byte[available];
entityInputStream.read(data);
@@ -140,4 +101,44 @@ private String maskHeaderValues(List