View Javadoc

1   package com.atlassian.marketplace.client.impl;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.ByteArrayOutputStream;
5   import java.io.InputStream;
6   import java.net.URI;
7   
8   import com.atlassian.marketplace.client.MpacException;
9   import com.atlassian.marketplace.client.api.Page;
10  import com.atlassian.marketplace.client.api.PageReader;
11  import com.atlassian.marketplace.client.api.PageReference;
12  import com.atlassian.marketplace.client.http.SimpleHttpResponse;
13  import com.atlassian.marketplace.client.model.Links;
14  import com.atlassian.marketplace.client.model.TestModelBuilders;
15  import com.atlassian.marketplace.client.util.UriBuilder;
16  
17  import com.google.common.base.Function;
18  import com.google.common.base.Functions;
19  
20  import static com.atlassian.marketplace.client.impl.ApiHelper.JSON;
21  import static com.atlassian.marketplace.client.impl.ApiHelper.closeQuietly;
22  
23  abstract class ApiImplBase
24  {
25      protected final ApiHelper apiHelper;
26      protected final InternalModel.MinimalLinks root;
27      protected final URI apiRoot;
28      
29      protected ApiImplBase(ApiHelper apiHelper, InternalModel.MinimalLinks root, String rootLinkRel) throws MpacException
30      {
31          this.apiHelper = apiHelper;
32          this.root = root;
33          this.apiRoot = apiHelper.requireLinkUri(root.getLinks(), rootLinkRel, root.getClass());
34      }
35      
36      protected URI getApiRoot()
37      {
38          return apiRoot;
39      }
40      
41      protected UriBuilder fromApiRoot()
42      {
43          return UriBuilder.fromUri(apiRoot);
44      }
45      
46      protected Links getLinksOnly(URI uri) throws MpacException
47      {
48          InternalModel.MinimalLinks rep = apiHelper.getEntity(uri, InternalModel.MinimalLinks.class);
49          return rep.getLinks();
50      }
51  
52      protected <T> T genericCreate(URI collectionUri, T entity) throws MpacException
53      {
54          return genericCreate(collectionUri, entity, Functions.<URI>identity());
55      }
56      
57      protected <T> T genericCreate(URI collectionUri, T entity, Function<URI, URI> resultUriTransform) throws MpacException
58      {
59          ByteArrayOutputStream bos = new ByteArrayOutputStream();
60          apiHelper.getEncoding().encode(bos, entity, false);
61          byte[] bytes = bos.toByteArray();
62          return createdOrUpdatedEntityResult(apiHelper.getHttp().post(apiHelper.resolveLink(collectionUri),
63              new ByteArrayInputStream(bytes), bytes.length, JSON, JSON),
64              entity.getClass(),
65              resultUriTransform);
66      }
67  
68      protected <T> T genericUpdate(URI uri, T original, T updated) throws MpacException
69      {
70          if (uri == TestModelBuilders.DEFAULT_URI)
71          {
72              // If the entity's self URI is DEFAULT_URI, then it's not a real, updatable entity that was obtained
73              // from the server - it's something the caller built.  In that case there's no point in trying to
74              // send a PATCH request to this fake URI; return a more informative error instead.
75              throw new MpacException.CannotUpdateNonServerSideEntity();
76          }
77          ByteArrayOutputStream bos = new ByteArrayOutputStream();
78          apiHelper.getEncoding().encodeChanges(bos, original, updated);
79          byte[] bytes = bos.toByteArray();
80          return createdOrUpdatedEntityResult(apiHelper.getHttp().patch(apiHelper.resolveLink(uri), bytes),
81              original.getClass(), Functions.<URI>identity());
82      }
83      
84      @SuppressWarnings("unchecked")
85      private <T> T createdOrUpdatedEntityResult(SimpleHttpResponse response, Class<?> entityClass,
86          Function<URI, URI> resultUriTransform) throws MpacException
87      {
88          try
89          {
90              int status = response.getStatus();
91              if (status == 200 || status == 201 || status == 204)
92              {
93                  for (String location: response.getHeader("Location"))
94                  {
95                      return apiHelper.getEntityUncached(resultUriTransform.apply(URI.create(location)), (Class<T>) entityClass);
96                  }
97                  throw new MpacException("Server did not return expected Location header");
98              }
99              throw apiHelper.responseException(response);
100         }
101         finally
102         {
103             closeQuietly(response);
104         }
105     }
106 
107     protected <T, U extends InternalModel.EntityCollection<T>> PageReader<T> pageReader(final Class<U> collectionRepClass)
108     {
109         return new PageReader<T>()
110         {
111             @Override
112             public Page<T> readPage(PageReference<T> ref, InputStream in) throws MpacException
113             {
114                 U rep = apiHelper.decode(in, collectionRepClass);
115                 return new PageImpl<T>(ref, rep.getLinks(), rep.getItems(), rep.getCount(), this);
116             }
117         };
118     }
119 }