View Javadoc
1   /*
2    * DavMail POP/IMAP/SMTP/CalDav/LDAP Exchange Gateway
3    * Copyright (C) 2010  Mickael Guessant
4    *
5    * This program is free software; you can redistribute it and/or
6    * modify it under the terms of the GNU General Public License
7    * as published by the Free Software Foundation; either version 2
8    * of the License, or (at your option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   * GNU General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License
16   * along with this program; if not, write to the Free Software
17   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18   */
19  
20  package davmail.exchange.graph;
21  
22  import davmail.Settings;
23  import davmail.exchange.ews.ExtendedFieldURI;
24  import davmail.exchange.ews.FieldURI;
25  import davmail.exchange.ews.IndexedFieldURI;
26  import org.apache.http.client.methods.HttpGet;
27  import org.apache.http.client.methods.HttpPost;
28  import org.apache.http.client.methods.HttpRequestBase;
29  import org.apache.http.client.utils.URIBuilder;
30  import org.apache.http.entity.ByteArrayEntity;
31  import org.codehaus.jettison.json.JSONException;
32  import org.codehaus.jettison.json.JSONObject;
33  
34  import java.io.IOException;
35  import java.net.URISyntaxException;
36  import java.nio.charset.StandardCharsets;
37  import java.util.ArrayList;
38  import java.util.List;
39  import java.util.Set;
40  
41  /**
42   * Build Microsoft graph request
43   */
44  public class GraphRequestBuilder {
45  
46      String method = "POST";
47      String baseUrl = Settings.GRAPH_URL;
48      String version = "beta";
49      String mailbox;
50      String objectType;
51  
52      String childType;
53  
54      String filter;
55  
56      Set<FieldURI> expandFields;
57  
58      String accessToken;
59  
60      JSONObject jsonBody = null;
61      private String objectId;
62  
63      /**
64       * Set property in Json body.
65       * @param name property name
66       * @param value property value
67       * @throws JSONException on error
68       */
69      public GraphRequestBuilder setProperty(String name, String value) throws JSONException {
70          if (jsonBody == null) {
71              jsonBody = new JSONObject();
72          }
73          jsonBody.put(name, value);
74          return this;
75      }
76  
77      /**
78       * Set epxand fields (returning attributes).
79       * @param expandFields set of fields to return
80       * @return this
81       */
82      public GraphRequestBuilder setExpandFields(Set<FieldURI> expandFields) {
83          this.expandFields = expandFields;
84          return this;
85      }
86  
87      public GraphRequestBuilder setObjectType(String objectType) {
88          this.objectType = objectType;
89          return this;
90      }
91  
92      public GraphRequestBuilder setChildType(String childType) {
93          this.childType = childType;
94          return this;
95      }
96  
97      public GraphRequestBuilder setFilter(String filter) {
98          this.filter = filter;
99          return this;
100     }
101 
102     public GraphRequestBuilder setAccessToken(String accessToken) {
103         this.accessToken = accessToken;
104         return this;
105     }
106 
107     public GraphRequestBuilder setMethod(String method) {
108         this.method = method;
109         return this;
110     }
111 
112     public GraphRequestBuilder setMailbox(String mailbox) {
113         this.mailbox = mailbox;
114         return this;
115     }
116 
117     public GraphRequestBuilder setObjectId(String objectId) {
118         this.objectId = objectId;
119         return this;
120     }
121 
122     /**
123      * Build request path based on version, username, object type and object id.
124      * @return request path
125      */
126     protected String buildPath() {
127         StringBuilder buffer = new StringBuilder();
128         buffer.append("/").append(version);
129         if (mailbox != null) {
130             buffer.append("/users/").append(mailbox);
131         } else {
132             buffer.append("/me");
133         }
134         if (objectType != null) {
135             buffer.append("/").append(objectType);
136         }
137         if (objectId != null) {
138             buffer.append("/").append(objectId);
139         }
140         if (childType != null) {
141             buffer.append("/").append(childType);
142         }
143 
144         return buffer.toString();
145     }
146 
147     /**
148      * Compute expand parameters from properties.
149      * @return $expand value
150      */
151     private String buildExpand() {
152         ArrayList<String> singleValueProperties = new ArrayList<>();
153         ArrayList<String> multiValueProperties = new ArrayList<>();
154         for (FieldURI fieldURI : expandFields) {
155             if (fieldURI instanceof ExtendedFieldURI) {
156                 singleValueProperties.add(fieldURI.getGraphId());
157             } else if (fieldURI instanceof IndexedFieldURI) {
158                 multiValueProperties.add(fieldURI.getGraphId());
159             }
160         }
161         StringBuilder expand = new StringBuilder();
162         if (!singleValueProperties.isEmpty()) {
163             expand.append("singleValueExtendedProperties($filter=");
164             appendExpandProperties(expand, singleValueProperties);
165             expand.append(")");
166         }
167         if (!multiValueProperties.isEmpty()) {
168             if (!singleValueProperties.isEmpty()) {
169                 expand.append(",");
170             }
171             expand.append("multiValueExtendedProperties($filter=");
172             appendExpandProperties(expand, multiValueProperties);
173             expand.append(")");
174         }
175         return expand.toString();
176     }
177 
178     protected void appendExpandProperties(StringBuilder buffer, List<String> properties) {
179         boolean first = true;
180         for (String id : properties) {
181             if (first) {
182                 first = false;
183             } else {
184                 buffer.append(" or ");
185             }
186             buffer.append("id eq '").append(id).append("'");
187         }
188     }
189 
190 
191     /**
192      * Build http request.
193      * @return Http request
194      * @throws IOException on error
195      */
196     public HttpRequestBase build() throws IOException {
197         try {
198             URIBuilder uriBuilder = new URIBuilder(baseUrl).setPath(buildPath());
199             if (expandFields != null) {
200                 uriBuilder.addParameter("$expand", buildExpand());
201             }
202 
203             if (filter != null) {
204                 uriBuilder.addParameter("$filter", filter);
205             }
206 
207             HttpRequestBase httpRequest;
208             if ("POST".equals(method)) {
209                 httpRequest = new HttpPost(uriBuilder.build());
210                 if (jsonBody != null) {
211                     ((HttpPost) httpRequest).setEntity(new ByteArrayEntity(jsonBody.toString().getBytes(StandardCharsets.UTF_8)));
212                 }
213             } else {
214                 // default to GET request
215                 httpRequest = new HttpGet(uriBuilder.build());
216             }
217             httpRequest.setHeader("Content-Type", "application/json");
218             httpRequest.setHeader("Authorization", "Bearer " + accessToken);
219 
220             return httpRequest;
221         } catch (URISyntaxException e) {
222             throw new IOException(e.getMessage(), e);
223         }
224     }
225 
226 }