summaryrefslogtreecommitdiffstats
path: root/mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/Server11Repository.java
blob: 4404fda25647fa1e497d7306bc543c30893592f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.mozilla.gecko.sync.repositories;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;

import org.mozilla.gecko.sync.InfoCollections;
import org.mozilla.gecko.sync.InfoConfiguration;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
import org.mozilla.gecko.sync.repositories.delegates.RepositorySessionCreationDelegate;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

/**
 * A Server11Repository implements fetching and storing against the Sync 1.1 API.
 * It doesn't do crypto: that's the job of the middleware.
 *
 * @author rnewman
 */
public class Server11Repository extends Repository {
  protected String collection;
  protected URI collectionURI;
  protected final AuthHeaderProvider authHeaderProvider;
  protected final InfoCollections infoCollections;

  private final InfoConfiguration infoConfiguration;

  /**
   * Construct a new repository that fetches and stores against the Sync 1.1. API.
   *
   * @param collection name.
   * @param storageURL full URL to storage endpoint.
   * @param authHeaderProvider to use in requests; may be null.
   * @param infoCollections instance; must not be null.
   * @throws URISyntaxException
   */
  public Server11Repository(@NonNull String collection, @NonNull String storageURL, AuthHeaderProvider authHeaderProvider, @NonNull InfoCollections infoCollections, @NonNull InfoConfiguration infoConfiguration) throws URISyntaxException {
    if (collection == null) {
      throw new IllegalArgumentException("collection must not be null");
    }
    if (storageURL == null) {
      throw new IllegalArgumentException("storageURL must not be null");
    }
    if (infoCollections == null) {
      throw new IllegalArgumentException("infoCollections must not be null");
    }
    this.collection = collection;
    this.collectionURI = new URI(storageURL + (storageURL.endsWith("/") ? collection : "/" + collection));
    this.authHeaderProvider = authHeaderProvider;
    this.infoCollections = infoCollections;
    this.infoConfiguration = infoConfiguration;
  }

  @Override
  public void createSession(RepositorySessionCreationDelegate delegate,
                            Context context) {
    delegate.onSessionCreated(new Server11RepositorySession(this));
  }

  public URI collectionURI() {
    return this.collectionURI;
  }

  public URI collectionURI(boolean full, long newer, long limit, String sort, String ids, String offset) throws URISyntaxException {
    ArrayList<String> params = new ArrayList<String>();
    if (full) {
      params.add("full=1");
    }
    if (newer >= 0) {
      // Translate local millisecond timestamps into server decimal seconds.
      String newerString = Utils.millisecondsToDecimalSecondsString(newer);
      params.add("newer=" + newerString);
    }
    if (limit > 0) {
      params.add("limit=" + limit);
    }
    if (sort != null) {
      params.add("sort=" + sort);       // We trust these values.
    }
    if (ids != null) {
      params.add("ids=" + ids);         // We trust these values.
    }
    if (offset != null) {
      // Offset comes straight out of HTTP headers and it is the responsibility of the caller to URI-escape it.
      params.add("offset=" + offset);
    }
    if (params.size() == 0) {
      return this.collectionURI;
    }

    StringBuilder out = new StringBuilder();
    char indicator = '?';
    for (String param : params) {
      out.append(indicator);
      indicator = '&';
      out.append(param);
    }
    String uri = this.collectionURI + out.toString();
    return new URI(uri);
  }

  public URI wboURI(String id) throws URISyntaxException {
    return new URI(this.collectionURI + "/" + id);
  }

  // Override these.
  @SuppressWarnings("static-method")
  public long getDefaultBatchLimit() {
    return -1;
  }

  @SuppressWarnings("static-method")
  public String getDefaultSort() {
    return null;
  }

  public long getDefaultTotalLimit() {
    return -1;
  }

  public AuthHeaderProvider getAuthHeaderProvider() {
    return authHeaderProvider;
  }

  public boolean updateNeeded(long lastSyncTimestamp) {
    return infoCollections.updateNeeded(collection, lastSyncTimestamp);
  }

  @Nullable
  public Long getCollectionLastModified() {
    return infoCollections.getTimestamp(collection);
  }

  public InfoConfiguration getInfoConfiguration() {
    return infoConfiguration;
  }
}