View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.chemistry.opencmis.client.bindings.spi.browser;
20  
21  import static org.apache.chemistry.opencmis.commons.impl.CollectionsHelper.isNullOrEmpty;
22  
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.OutputStream;
26  import java.math.BigInteger;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
31  import org.apache.chemistry.opencmis.client.bindings.spi.http.Output;
32  import org.apache.chemistry.opencmis.client.bindings.spi.http.Response;
33  import org.apache.chemistry.opencmis.commons.SessionParameter;
34  import org.apache.chemistry.opencmis.commons.data.Acl;
35  import org.apache.chemistry.opencmis.commons.data.AllowableActions;
36  import org.apache.chemistry.opencmis.commons.data.BulkUpdateObjectIdAndChangeToken;
37  import org.apache.chemistry.opencmis.commons.data.ContentStream;
38  import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
39  import org.apache.chemistry.opencmis.commons.data.FailedToDeleteData;
40  import org.apache.chemistry.opencmis.commons.data.ObjectData;
41  import org.apache.chemistry.opencmis.commons.data.Properties;
42  import org.apache.chemistry.opencmis.commons.data.RenditionData;
43  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
44  import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
45  import org.apache.chemistry.opencmis.commons.enums.VersioningState;
46  import org.apache.chemistry.opencmis.commons.exceptions.CmisConnectionException;
47  import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
48  import org.apache.chemistry.opencmis.commons.impl.Constants;
49  import org.apache.chemistry.opencmis.commons.impl.IOUtils;
50  import org.apache.chemistry.opencmis.commons.impl.JSONConverter;
51  import org.apache.chemistry.opencmis.commons.impl.MimeHelper;
52  import org.apache.chemistry.opencmis.commons.impl.TypeCache;
53  import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
54  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
55  import org.apache.chemistry.opencmis.commons.impl.dataobjects.FailedToDeleteDataImpl;
56  import org.apache.chemistry.opencmis.commons.impl.dataobjects.PartialContentStreamImpl;
57  import org.apache.chemistry.opencmis.commons.spi.Holder;
58  import org.apache.chemistry.opencmis.commons.spi.ObjectService;
59  
60  /**
61   * Object Service Browser Binding client.
62   */
63  public class ObjectServiceImpl extends AbstractBrowserBindingService implements ObjectService {
64  
65      /**
66       * Constructor.
67       */
68      public ObjectServiceImpl(BindingSession session) {
69          setSession(session);
70      }
71  
72      @Override
73      public String createDocument(String repositoryId, Properties properties, String folderId,
74              ContentStream contentStream, VersioningState versioningState, List<String> policies, Acl addAces,
75              Acl removeAces, ExtensionsData extension) {
76          // build URL
77          UrlBuilder url = folderId != null ? getObjectUrl(repositoryId, folderId) : getRepositoryUrl(repositoryId);
78  
79          // prepare form data
80          final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_CREATE_DOCUMENT, contentStream);
81          formData.addPropertiesParameters(properties, getDateTimeFormat());
82          formData.addParameter(Constants.PARAM_VERSIONIG_STATE, versioningState);
83          formData.addPoliciesParameters(policies);
84          formData.addAddAcesParameters(addAces);
85          formData.addRemoveAcesParameters(removeAces);
86          formData.addSuccinctFlag(getSuccinct());
87  
88          // send and parse
89          Response resp = post(url, formData.getContentType(), new Output() {
90              @Override
91              public void write(OutputStream out) throws IOException {
92                  formData.write(out);
93              }
94          });
95  
96          Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
97  
98          TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
99  
100         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
101 
102         return newObj == null ? null : newObj.getId();
103     }
104 
105     @Override
106     public String createDocumentFromSource(String repositoryId, String sourceId, Properties properties,
107             String folderId, VersioningState versioningState, List<String> policies, Acl addAces, Acl removeAces,
108             ExtensionsData extension) {
109         // build URL
110         UrlBuilder url = folderId != null ? getObjectUrl(repositoryId, folderId) : getRepositoryUrl(repositoryId);
111 
112         // prepare form data
113         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_CREATE_DOCUMENT_FROM_SOURCE);
114         formData.addParameter(Constants.PARAM_SOURCE_ID, sourceId);
115         formData.addPropertiesParameters(properties, getDateTimeFormat());
116         formData.addParameter(Constants.PARAM_VERSIONIG_STATE, versioningState);
117         formData.addPoliciesParameters(policies);
118         formData.addAddAcesParameters(addAces);
119         formData.addRemoveAcesParameters(removeAces);
120         formData.addSuccinctFlag(getSuccinct());
121 
122         // send and parse
123         Response resp = post(url, formData.getContentType(), new Output() {
124             @Override
125             public void write(OutputStream out) throws IOException {
126                 formData.write(out);
127             }
128         });
129 
130         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
131 
132         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
133 
134         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
135 
136         return newObj == null ? null : newObj.getId();
137     }
138 
139     @Override
140     public String createFolder(String repositoryId, Properties properties, String folderId, List<String> policies,
141             Acl addAces, Acl removeAces, ExtensionsData extension) {
142         // build URL
143         UrlBuilder url = getObjectUrl(repositoryId, folderId);
144 
145         // prepare form data
146         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_CREATE_FOLDER);
147         formData.addPropertiesParameters(properties, getDateTimeFormat());
148         formData.addPoliciesParameters(policies);
149         formData.addAddAcesParameters(addAces);
150         formData.addRemoveAcesParameters(removeAces);
151         formData.addSuccinctFlag(getSuccinct());
152 
153         // send and parse
154         Response resp = post(url, formData.getContentType(), new Output() {
155             @Override
156             public void write(OutputStream out) throws IOException {
157                 formData.write(out);
158             }
159         });
160 
161         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
162 
163         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
164 
165         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
166 
167         return newObj == null ? null : newObj.getId();
168     }
169 
170     @Override
171     public String createRelationship(String repositoryId, Properties properties, List<String> policies, Acl addAces,
172             Acl removeAces, ExtensionsData extension) {
173         // build URL
174         UrlBuilder url = getRepositoryUrl(repositoryId);
175 
176         // prepare form data
177         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_CREATE_RELATIONSHIP);
178         formData.addPropertiesParameters(properties, getDateTimeFormat());
179         formData.addPoliciesParameters(policies);
180         formData.addAddAcesParameters(addAces);
181         formData.addRemoveAcesParameters(removeAces);
182         formData.addSuccinctFlag(getSuccinct());
183 
184         // send and parse
185         Response resp = post(url, formData.getContentType(), new Output() {
186             @Override
187             public void write(OutputStream out) throws IOException {
188                 formData.write(out);
189             }
190         });
191 
192         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
193 
194         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
195 
196         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
197 
198         return newObj == null ? null : newObj.getId();
199     }
200 
201     @Override
202     public String createPolicy(String repositoryId, Properties properties, String folderId, List<String> policies,
203             Acl addAces, Acl removeAces, ExtensionsData extension) {
204         // build URL
205         UrlBuilder url = folderId != null ? getObjectUrl(repositoryId, folderId) : getRepositoryUrl(repositoryId);
206 
207         // prepare form data
208         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_CREATE_POLICY);
209         formData.addPropertiesParameters(properties, getDateTimeFormat());
210         formData.addPoliciesParameters(policies);
211         formData.addAddAcesParameters(addAces);
212         formData.addRemoveAcesParameters(removeAces);
213         formData.addSuccinctFlag(getSuccinct());
214 
215         // send and parse
216         Response resp = post(url, formData.getContentType(), new Output() {
217             @Override
218             public void write(OutputStream out) throws IOException {
219                 formData.write(out);
220             }
221         });
222 
223         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
224 
225         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
226 
227         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
228 
229         return newObj == null ? null : newObj.getId();
230     }
231 
232     @Override
233     public String createItem(String repositoryId, Properties properties, String folderId, List<String> policies,
234             Acl addAces, Acl removeAces, ExtensionsData extension) {
235         // build URL
236         UrlBuilder url = folderId != null ? getObjectUrl(repositoryId, folderId) : getRepositoryUrl(repositoryId);
237 
238         // prepare form data
239         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_CREATE_ITEM);
240         formData.addPropertiesParameters(properties, getDateTimeFormat());
241         formData.addPoliciesParameters(policies);
242         formData.addAddAcesParameters(addAces);
243         formData.addRemoveAcesParameters(removeAces);
244         formData.addSuccinctFlag(getSuccinct());
245 
246         // send and parse
247         Response resp = post(url, formData.getContentType(), new Output() {
248             @Override
249             public void write(OutputStream out) throws IOException {
250                 formData.write(out);
251             }
252         });
253 
254         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
255 
256         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
257 
258         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
259 
260         return newObj == null ? null : newObj.getId();
261     }
262 
263     @Override
264     public AllowableActions getAllowableActions(String repositoryId, String objectId, ExtensionsData extension) {
265         // build URL
266         UrlBuilder url = getObjectUrl(repositoryId, objectId, Constants.SELECTOR_ALLOWABLEACTIONS);
267 
268         // read and parse
269         Response resp = read(url);
270         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
271 
272         return JSONConverter.convertAllowableActions(json);
273     }
274 
275     @Override
276     public ObjectData getObject(String repositoryId, String objectId, String filter, Boolean includeAllowableActions,
277             IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
278             Boolean includeAcl, ExtensionsData extension) {
279         // build URL
280         UrlBuilder url = getObjectUrl(repositoryId, objectId, Constants.SELECTOR_OBJECT);
281         url.addParameter(Constants.PARAM_FILTER, filter);
282         url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
283         url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
284         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
285         url.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds);
286         url.addParameter(Constants.PARAM_ACL, includeAcl);
287         url.addParameter(Constants.PARAM_SUCCINCT, getSuccinctParameter());
288         url.addParameter(Constants.PARAM_DATETIME_FORMAT, getDateTimeFormatParameter());
289 
290         // read and parse
291         Response resp = read(url);
292         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
293 
294         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
295 
296         return JSONConverter.convertObject(json, typeCache);
297     }
298 
299     @Override
300     public ObjectData getObjectByPath(String repositoryId, String path, String filter, Boolean includeAllowableActions,
301             IncludeRelationships includeRelationships, String renditionFilter, Boolean includePolicyIds,
302             Boolean includeAcl, ExtensionsData extension) {
303         // build URL
304         UrlBuilder url = getPathUrl(repositoryId, path, Constants.SELECTOR_OBJECT);
305         url.addParameter(Constants.PARAM_FILTER, filter);
306         url.addParameter(Constants.PARAM_ALLOWABLE_ACTIONS, includeAllowableActions);
307         url.addParameter(Constants.PARAM_RELATIONSHIPS, includeRelationships);
308         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
309         url.addParameter(Constants.PARAM_POLICY_IDS, includePolicyIds);
310         url.addParameter(Constants.PARAM_ACL, includeAcl);
311         url.addParameter(Constants.PARAM_SUCCINCT, getSuccinctParameter());
312         url.addParameter(Constants.PARAM_DATETIME_FORMAT, getDateTimeFormatParameter());
313 
314         // read and parse
315         Response resp = read(url);
316         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
317 
318         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
319 
320         return JSONConverter.convertObject(json, typeCache);
321     }
322 
323     @Override
324     public Properties getProperties(String repositoryId, String objectId, String filter, ExtensionsData extension) {
325         // build URL
326         UrlBuilder url = getObjectUrl(repositoryId, objectId, Constants.SELECTOR_PROPERTIES);
327         url.addParameter(Constants.PARAM_FILTER, filter);
328         url.addParameter(Constants.PARAM_SUCCINCT, getSuccinctParameter());
329         url.addParameter(Constants.PARAM_DATETIME_FORMAT, getDateTimeFormatParameter());
330 
331         // read and parse
332         Response resp = read(url);
333         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
334 
335         if (getSuccinct()) {
336             TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
337             return JSONConverter.convertSuccinctProperties(json, null, typeCache);
338         } else {
339             return JSONConverter.convertProperties(json, null);
340         }
341     }
342 
343     @Override
344     public List<RenditionData> getRenditions(String repositoryId, String objectId, String renditionFilter,
345             BigInteger maxItems, BigInteger skipCount, ExtensionsData extension) {
346         // build URL
347         UrlBuilder url = getObjectUrl(repositoryId, objectId, Constants.SELECTOR_RENDITIONS);
348         url.addParameter(Constants.PARAM_RENDITION_FILTER, renditionFilter);
349         url.addParameter(Constants.PARAM_MAX_ITEMS, maxItems);
350         url.addParameter(Constants.PARAM_SKIP_COUNT, skipCount);
351 
352         // read and parse
353         Response resp = read(url);
354         List<Object> json = parseArray(resp.getStream(), resp.getCharset());
355 
356         return JSONConverter.convertRenditions(json);
357     }
358 
359     @Override
360     public ContentStream getContentStream(String repositoryId, String objectId, String streamId, BigInteger offset,
361             BigInteger length, ExtensionsData extension) {
362 
363         // build URL
364         UrlBuilder url = getObjectUrl(repositoryId, objectId, Constants.SELECTOR_CONTENT);
365         url.addParameter(Constants.PARAM_STREAM_ID, streamId);
366 
367         // get the content
368         Response resp = getHttpInvoker().invokeGET(url, getSession(), offset, length);
369 
370         // check response code
371         if ((resp.getResponseCode() != 200) && (resp.getResponseCode() != 206)) {
372             throw convertStatusCode(resp.getResponseCode(), resp.getResponseMessage(), resp.getErrorContent(), null);
373         }
374 
375         // get filename from Content-Disposition header
376         String filename = null;
377         String contentDisposition = resp.getContentDisposition();
378         if (contentDisposition != null) {
379             filename = MimeHelper.decodeContentDispositionFilename(contentDisposition);
380         }
381 
382         // build result object
383         ContentStreamImpl result;
384         if (resp.getResponseCode() == 206) {
385             result = new PartialContentStreamImpl();
386         } else {
387             result = new ContentStreamImpl();
388         }
389 
390         result.setFileName(filename);
391         result.setLength(resp.getContentLength());
392         result.setMimeType(resp.getContentTypeHeader());
393         result.setStream(resp.getStream());
394 
395         return result;
396     }
397 
398     @Override
399     public void updateProperties(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
400             Properties properties, ExtensionsData extension) {
401         // we need an object ID
402         if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
403             throw new CmisInvalidArgumentException("Object ID must be set!");
404         }
405 
406         // build URL
407         UrlBuilder url = getObjectUrl(repositoryId, objectId.getValue());
408 
409         // prepare form data
410         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_UPDATE_PROPERTIES);
411         formData.addPropertiesParameters(properties, getDateTimeFormat());
412         formData.addParameter(Constants.PARAM_CHANGE_TOKEN,
413                 (changeToken == null || getSession().get(SessionParameter.OMIT_CHANGE_TOKENS, false) ? null
414                         : changeToken.getValue()));
415         formData.addSuccinctFlag(getSuccinct());
416 
417         // send and parse
418         Response resp = post(url, formData.getContentType(), new Output() {
419             @Override
420             public void write(OutputStream out) throws IOException {
421                 formData.write(out);
422             }
423         });
424 
425         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
426 
427         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
428 
429         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
430 
431         objectId.setValue(newObj == null ? null : newObj.getId());
432 
433         setChangeToken(changeToken, newObj);
434     }
435 
436     @Override
437     public List<BulkUpdateObjectIdAndChangeToken> bulkUpdateProperties(String repositoryId,
438             List<BulkUpdateObjectIdAndChangeToken> objectIdAndChangeToken, Properties properties,
439             List<String> addSecondaryTypeIds, List<String> removeSecondaryTypeIds, ExtensionsData extension) {
440         // we need object ids
441         if (isNullOrEmpty(objectIdAndChangeToken)) {
442             throw new CmisInvalidArgumentException("Object ids must be set!");
443         }
444 
445         // build URL
446         UrlBuilder url = getRepositoryUrl(repositoryId);
447 
448         // prepare form data
449         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_BULK_UPDATE);
450         formData.addObjectIdsAndChangeTokens(objectIdAndChangeToken);
451         formData.addPropertiesParameters(properties, getDateTimeFormat());
452         formData.addSecondaryTypeIds(addSecondaryTypeIds);
453         formData.removeSecondaryTypeIds(removeSecondaryTypeIds);
454 
455         // send and parse
456         Response resp = post(url, formData.getContentType(), new Output() {
457             @Override
458             public void write(OutputStream out) throws IOException {
459                 formData.write(out);
460             }
461         });
462 
463         List<Object> json = parseArray(resp.getStream(), resp.getCharset());
464 
465         return JSONConverter.convertBulkUpdate(json);
466     }
467 
468     @Override
469     public void moveObject(String repositoryId, Holder<String> objectId, String targetFolderId, String sourceFolderId,
470             ExtensionsData extension) {
471         // we need an object id
472         if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
473             throw new CmisInvalidArgumentException("Object ID must be set!");
474         }
475 
476         // build URL
477         UrlBuilder url = getObjectUrl(repositoryId, objectId.getValue());
478 
479         // prepare form data
480         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_MOVE);
481         formData.addParameter(Constants.PARAM_TARGET_FOLDER_ID, targetFolderId);
482         formData.addParameter(Constants.PARAM_SOURCE_FOLDER_ID, sourceFolderId);
483         formData.addSuccinctFlag(getSuccinct());
484 
485         // send and parse
486         Response resp = post(url, formData.getContentType(), new Output() {
487             @Override
488             public void write(OutputStream out) throws IOException {
489                 formData.write(out);
490             }
491         });
492 
493         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
494 
495         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
496 
497         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
498 
499         objectId.setValue(newObj == null ? null : newObj.getId());
500     }
501 
502     @Override
503     public void deleteObject(String repositoryId, String objectId, Boolean allVersions, ExtensionsData extension) {
504         // build URL
505         UrlBuilder url = getObjectUrl(repositoryId, objectId);
506 
507         // prepare form data
508         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_DELETE);
509         formData.addParameter(Constants.PARAM_ALL_VERSIONS, allVersions);
510 
511         // send
512         postAndConsume(url, formData.getContentType(), new Output() {
513             @Override
514             public void write(OutputStream out) throws IOException {
515                 formData.write(out);
516             }
517         });
518     }
519 
520     @Override
521     public FailedToDeleteData deleteTree(String repositoryId, String folderId, Boolean allVersions,
522             UnfileObject unfileObjects, Boolean continueOnFailure, ExtensionsData extension) {
523         // build URL
524         UrlBuilder url = getObjectUrl(repositoryId, folderId);
525 
526         // prepare form data
527         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_DELETE_TREE);
528         formData.addParameter(Constants.PARAM_ALL_VERSIONS, allVersions);
529         formData.addParameter(Constants.PARAM_UNFILE_OBJECTS, unfileObjects);
530         formData.addParameter(Constants.PARAM_CONTINUE_ON_FAILURE, continueOnFailure);
531 
532         // send
533         Response resp = post(url, formData.getContentType(), new Output() {
534             @Override
535             public void write(OutputStream out) throws IOException {
536                 formData.write(out);
537             }
538         });
539 
540         if (resp.hasResponseStream()) {
541             try {
542                 InputStream responseStream = IOUtils.checkForBytes(resp.getStream(), 8192);
543                 if (responseStream != null) {
544                     Map<String, Object> json = parseObject(responseStream, resp.getCharset());
545                     return JSONConverter.convertFailedToDelete(json);
546                 }
547             } catch (IOException e) {
548                 throw new CmisConnectionException("Cannot read response!", e);
549             }
550         }
551 
552         return new FailedToDeleteDataImpl();
553     }
554 
555     @Override
556     public void setContentStream(String repositoryId, Holder<String> objectId, Boolean overwriteFlag,
557             Holder<String> changeToken, ContentStream contentStream, ExtensionsData extension) {
558         // we need an object id
559         if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
560             throw new CmisInvalidArgumentException("Object ID must be set!");
561         }
562 
563         // build URL
564         UrlBuilder url = getObjectUrl(repositoryId, objectId.getValue());
565 
566         // prepare form data
567         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_SET_CONTENT, contentStream);
568         formData.addParameter(Constants.PARAM_OVERWRITE_FLAG, overwriteFlag);
569         formData.addParameter(Constants.PARAM_CHANGE_TOKEN,
570                 (changeToken == null || getSession().get(SessionParameter.OMIT_CHANGE_TOKENS, false) ? null
571                         : changeToken.getValue()));
572         formData.addSuccinctFlag(getSuccinct());
573 
574         // send and parse
575         Response resp = post(url, formData.getContentType(), new Output() {
576             @Override
577             public void write(OutputStream out) throws IOException {
578                 formData.write(out);
579             }
580         });
581 
582         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
583 
584         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
585 
586         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
587 
588         objectId.setValue(newObj == null ? null : newObj.getId());
589 
590         setChangeToken(changeToken, newObj);
591     }
592 
593     @Override
594     public void appendContentStream(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
595             ContentStream contentStream, boolean isLastChunk, ExtensionsData extension) {
596         // we need an object id
597         if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
598             throw new CmisInvalidArgumentException("Object ID must be set!");
599         }
600 
601         // build URL
602         UrlBuilder url = getObjectUrl(repositoryId, objectId.getValue());
603 
604         // prepare form data
605         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_APPEND_CONTENT, contentStream);
606         formData.addParameter(Constants.CONTROL_IS_LAST_CHUNK, isLastChunk);
607         formData.addParameter(Constants.PARAM_CHANGE_TOKEN,
608                 (changeToken == null || getSession().get(SessionParameter.OMIT_CHANGE_TOKENS, false) ? null
609                         : changeToken.getValue()));
610         formData.addSuccinctFlag(getSuccinct());
611 
612         // send and parse
613         Response resp = post(url, formData.getContentType(), new Output() {
614             @Override
615             public void write(OutputStream out) throws IOException {
616                 formData.write(out);
617             }
618         });
619 
620         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
621 
622         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
623 
624         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
625 
626         objectId.setValue(newObj == null ? null : newObj.getId());
627 
628         setChangeToken(changeToken, newObj);
629     }
630 
631     @Override
632     public void deleteContentStream(String repositoryId, Holder<String> objectId, Holder<String> changeToken,
633             ExtensionsData extension) {
634         // we need an object id
635         if ((objectId == null) || (objectId.getValue() == null) || (objectId.getValue().length() == 0)) {
636             throw new CmisInvalidArgumentException("Object ID must be set!");
637         }
638 
639         // build URL
640         UrlBuilder url = getObjectUrl(repositoryId, objectId.getValue());
641 
642         // prepare form data
643         final FormDataWriter formData = new FormDataWriter(Constants.CMISACTION_DELETE_CONTENT);
644         formData.addParameter(Constants.PARAM_CHANGE_TOKEN,
645                 (changeToken == null || getSession().get(SessionParameter.OMIT_CHANGE_TOKENS, false) ? null
646                         : changeToken.getValue()));
647         formData.addSuccinctFlag(getSuccinct());
648 
649         // send and parse
650         Response resp = post(url, formData.getContentType(), new Output() {
651             @Override
652             public void write(OutputStream out) throws IOException {
653                 formData.write(out);
654             }
655         });
656 
657         Map<String, Object> json = parseObject(resp.getStream(), resp.getCharset());
658 
659         TypeCache typeCache = new ClientTypeCacheImpl(repositoryId, this);
660 
661         ObjectData newObj = JSONConverter.convertObject(json, typeCache);
662 
663         objectId.setValue(newObj == null ? null : newObj.getId());
664 
665         setChangeToken(changeToken, newObj);
666     }
667 }