1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package davmail.exchange.graph;
21
22 import davmail.Settings;
23 import davmail.exchange.ExchangeSession;
24 import davmail.util.IOUtil;
25 import davmail.util.StringUtil;
26 import org.apache.http.client.methods.HttpDelete;
27 import org.apache.http.client.methods.HttpGet;
28 import org.apache.http.client.methods.HttpPatch;
29 import org.apache.http.client.methods.HttpPost;
30 import org.apache.http.client.methods.HttpPut;
31 import org.apache.http.client.methods.HttpRequestBase;
32 import org.apache.http.client.utils.URIBuilder;
33 import org.apache.http.entity.ByteArrayEntity;
34 import org.apache.log4j.Logger;
35 import org.codehaus.jettison.json.JSONException;
36 import org.codehaus.jettison.json.JSONObject;
37
38 import java.io.IOException;
39 import java.net.URISyntaxException;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Set;
45
46
47
48
49 public class GraphRequestBuilder {
50 protected static final Logger LOGGER = Logger.getLogger("davmail.exchange.graph.GraphRequestBuilder");
51
52 String method = "POST";
53
54 String contentType = "application/json";
55 String baseUrl = Settings.getGraphUrl();
56 String version = Settings.getProperty("davmail.graphVersion", "beta");
57 String mailbox;
58 String objectType;
59
60 String childType;
61 String childId;
62 String childSuffix;
63
64 String select;
65 String expand;
66
67 String filter;
68 String search;
69 int sizeLimit;
70
71 String startDateTime;
72 String endDateTime;
73
74 String timeZone;
75
76 Set<GraphField> selectFields;
77
78 String accessToken;
79
80 JSONObject jsonBody = null;
81
82
83
84
85 HashMap<String, String> headerMap;
86
87 byte[] mimeContent;
88 private String objectId;
89
90
91
92
93
94
95
96 public GraphRequestBuilder setProperty(String name, String value) throws JSONException {
97 if (jsonBody == null) {
98 jsonBody = new JSONObject();
99 }
100 jsonBody.put(name, value);
101 return this;
102 }
103
104
105
106
107
108 public GraphRequestBuilder setJsonBody(JSONObject jsonBody) {
109 this.jsonBody = jsonBody;
110 return this;
111 }
112
113 public GraphRequestBuilder addHeader(String name, String value) {
114 if (headerMap == null) {
115 headerMap = new HashMap<String, String>();
116 }
117 headerMap.put(name, value);
118 return this;
119 }
120
121
122
123
124
125
126 public GraphRequestBuilder setSelectFields(Set<GraphField> selectFields) {
127 this.selectFields = selectFields;
128 computeSelectAndExpand();
129 return this;
130 }
131
132 public GraphRequestBuilder setVersion(String version) {
133 this.version = version;
134 return this;
135 }
136
137 public GraphRequestBuilder setObjectType(String objectType) {
138 this.objectType = objectType;
139 return this;
140 }
141
142 public GraphRequestBuilder setChildType(String childType) {
143 this.childType = childType;
144 return this;
145 }
146
147 public GraphRequestBuilder setChildId(String childId) {
148 this.childId = childId;
149 return this;
150 }
151
152 public GraphRequestBuilder setChildSuffix(String childSuffix) {
153 this.childSuffix = childSuffix;
154 return this;
155 }
156
157 public GraphRequestBuilder setFilter(String filter) {
158 this.filter = filter;
159 return this;
160 }
161
162 public GraphRequestBuilder setFilter(ExchangeSession.Condition condition) {
163 if (condition != null && !condition.isEmpty()) {
164 StringBuilder buffer = new StringBuilder();
165 condition.appendTo(buffer);
166 this.filter = buffer.toString();
167 LOGGER.debug("filter: " + filter);
168 }
169 return this;
170 }
171
172 public GraphRequestBuilder setSearch(String search) {
173 this.search = search;
174 return this;
175 }
176
177 public GraphRequestBuilder setStartDateTime(String startDateTime) {
178 this.startDateTime = startDateTime;
179 return this;
180 }
181
182 public GraphRequestBuilder setEndDateTime(String endDateTime) {
183 this.endDateTime = endDateTime;
184 return this;
185 }
186
187 public GraphRequestBuilder setTimezone(String timeZone) {
188 this.timeZone = timeZone;
189 return this;
190 }
191
192 public GraphRequestBuilder setAccessToken(String accessToken) {
193 this.accessToken = accessToken;
194 return this;
195 }
196
197 public GraphRequestBuilder setMethod(String method) {
198 this.method = method;
199 return this;
200 }
201
202 public GraphRequestBuilder setContentType(String contentType) {
203 this.contentType = contentType;
204 return this;
205 }
206
207 public GraphRequestBuilder setMimeContent(byte[] mimeContent) {
208 this.mimeContent = mimeContent;
209 return this;
210 }
211
212 public GraphRequestBuilder setMailbox(String mailbox) {
213 this.mailbox = mailbox;
214 return this;
215 }
216
217 public GraphRequestBuilder setObjectId(String objectId) {
218 this.objectId = objectId;
219 return this;
220 }
221
222 public GraphRequestBuilder setSelect(String select) {
223 this.select = select;
224 return this;
225 }
226
227 public GraphRequestBuilder setSizeLimit(int sizeLimit) {
228 this.sizeLimit = sizeLimit;
229 return this;
230 }
231
232
233
234
235
236 protected String buildPath() {
237 StringBuilder buffer = new StringBuilder();
238 buffer.append("/").append(version);
239 if ("orgcontacts".equals(objectType)) {
240
241 buffer.append("/contacts");
242 } else if ("users".equals(objectType)) {
243 buffer.append("/users");
244 } else {
245 if (mailbox != null) {
246 buffer.append("/users/").append(mailbox);
247 } else {
248 buffer.append("/me");
249 }
250 if (objectType != null) {
251 buffer.append("/").append(objectType);
252 }
253 }
254 if (objectId != null) {
255 buffer.append("/").append(objectId);
256 }
257 if (childType != null) {
258 buffer.append("/").append(childType);
259 }
260 if (childId != null) {
261 buffer.append("/").append(childId);
262 }
263 if (childSuffix != null) {
264 buffer.append("/").append(childSuffix);
265 }
266
267 return buffer.toString();
268 }
269
270
271
272
273 private void computeSelectAndExpand() {
274 ArrayList<String> singleValueProperties = new ArrayList<>();
275 ArrayList<String> multiValueProperties = new ArrayList<>();
276 ArrayList<String> selectProperties = new ArrayList<>();
277 for (GraphField field : selectFields) {
278 if (field.isExtended()) {
279 if (field.isMultiValued()) {
280 multiValueProperties.add(field.getGraphId());
281 } else {
282 singleValueProperties.add(field.getGraphId());
283 if (field.getAlias().startsWith("smtpemail")) {
284
285 selectProperties.add("emailAddresses");
286 }
287 }
288
289 } else if (!GraphField.getGraphId("@odata.etag").equals(field.getGraphId())){
290 selectProperties.add(field.getGraphId());
291 }
292 }
293 StringBuilder expandBuffer = new StringBuilder();
294 if (!singleValueProperties.isEmpty()) {
295 expandBuffer.append("singleValueExtendedProperties($filter=");
296 appendExpandProperties(expandBuffer, singleValueProperties);
297 expandBuffer.append(")");
298 }
299 if (!multiValueProperties.isEmpty()) {
300 if (!singleValueProperties.isEmpty()) {
301 expandBuffer.append(",");
302 }
303 expandBuffer.append("multiValueExtendedProperties($filter=");
304 appendExpandProperties(expandBuffer, multiValueProperties);
305 expandBuffer.append(")");
306 }
307 expand = expandBuffer.toString();
308 if (!selectProperties.isEmpty()) {
309 select = String.join(",", selectProperties);
310 }
311 }
312
313
314
315
316
317
318 protected void appendExpandProperties(StringBuilder buffer, List<String> properties) {
319 boolean first = true;
320 for (String id : properties) {
321 if (first) {
322 first = false;
323 } else {
324 buffer.append(" or ");
325 }
326 buffer.append("id eq '").append(id).append("'");
327 }
328 }
329
330
331
332
333
334
335
336 public HttpRequestBase build() throws IOException {
337 try {
338 URIBuilder uriBuilder = new URIBuilder(baseUrl).setPath(buildPath());
339 if (select != null) {
340 uriBuilder.addParameter("$select", select);
341 }
342
343 if (selectFields != null) {
344 uriBuilder.addParameter("$expand", expand);
345 }
346
347 if (filter != null) {
348 uriBuilder.addParameter("$filter", filter);
349 }
350
351 if (search != null) {
352 uriBuilder.addParameter("$search", "\""+ StringUtil.escapeDoubleQuotes(search)+"\"");
353 }
354
355 if (startDateTime != null) {
356 uriBuilder.addParameter("startDateTime", startDateTime);
357 }
358
359 if (endDateTime != null) {
360 uriBuilder.addParameter("endDateTime", endDateTime);
361 }
362
363 if (sizeLimit != 0) {
364 uriBuilder.addParameter("$top", String.valueOf(sizeLimit));
365 }
366
367 HttpRequestBase httpRequest;
368
369 if ("POST".equals(method)) {
370 httpRequest = new HttpPost(uriBuilder.build());
371 if (mimeContent != null) {
372 ((HttpPost) httpRequest).setEntity(new ByteArrayEntity(mimeContent));
373 } else if (jsonBody != null) {
374 ((HttpPost) httpRequest).setEntity(new ByteArrayEntity(IOUtil.convertToBytes(jsonBody)));
375 }
376 } else if (HttpPut.METHOD_NAME.equals(method)) {
377
378 httpRequest = new HttpPut(uriBuilder.build());
379 if (mimeContent != null) {
380 ((HttpPut) httpRequest).setEntity(new ByteArrayEntity(mimeContent));
381 }
382 } else if (HttpPatch.METHOD_NAME.equals(method)) {
383 httpRequest = new HttpPatch(uriBuilder.build());
384 if (jsonBody != null) {
385 ((HttpPatch) httpRequest).setEntity(new ByteArrayEntity(IOUtil.convertToBytes(jsonBody)));
386 }
387 } else if ("DELETE".equals(method)) {
388 httpRequest = new HttpDelete(uriBuilder.build());
389 } else {
390
391 httpRequest = new HttpGet(uriBuilder.build());
392 }
393 httpRequest.setHeader("Content-Type", contentType);
394 httpRequest.setHeader("Authorization", "Bearer " + accessToken);
395
396
397 if (headerMap != null) {
398 for (Map.Entry<String, String> header : headerMap.entrySet()) {
399 httpRequest.addHeader(header.getKey(), header.getValue());
400 }
401 }
402
403 if (timeZone != null) {
404 httpRequest.setHeader("Prefer", "outlook.timezone=\"" + timeZone + "\"");
405 }
406
407 if (LOGGER.isDebugEnabled()) {
408 LOGGER.debug(httpRequest.getMethod() + " " + httpRequest.getURI());
409 if (jsonBody != null) {
410 LOGGER.debug(jsonBody.toString());
411 }
412 }
413
414 return httpRequest;
415 } catch (URISyntaxException e) {
416 throw new IOException(e.getMessage(), e);
417 }
418 }
419
420 }