This project has retired. For details please refer to its Attic page.
FormDataWriter xref

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 java.io.BufferedInputStream;
22  import java.io.ByteArrayInputStream;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  import java.net.URLEncoder;
26  import java.util.GregorianCalendar;
27  import java.util.LinkedHashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  import org.apache.chemistry.opencmis.commons.data.Ace;
32  import org.apache.chemistry.opencmis.commons.data.Acl;
33  import org.apache.chemistry.opencmis.commons.data.ContentStream;
34  import org.apache.chemistry.opencmis.commons.data.Properties;
35  import org.apache.chemistry.opencmis.commons.data.PropertyData;
36  import org.apache.chemistry.opencmis.commons.impl.Constants;
37  import org.apache.chemistry.opencmis.commons.impl.MimeHelper;
38  import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
39  
40  public class FormDataWriter {
41  
42      private static final String CONTENT_TYPE_URLENCODED = "application/x-www-form-urlencoded;charset=utf-8";
43      private static final String CONTENT_TYPE_FORMDATA = "multipart/form-data; boundary=";
44      private static final String CRLF = "\r\n";
45      private static final int BUFFER_SIZE = 64 * 1024;
46  
47      private final String boundary;
48      private final Map<String, String> parameters = new LinkedHashMap<String, String>();
49      private ContentStream contentStream;
50  
51      public FormDataWriter(String action) {
52          this(action, null);
53      }
54  
55      public FormDataWriter(String action, ContentStream contentStream) {
56          addParameter(Constants.CONTROL_CMISACTION, action);
57          this.contentStream = contentStream;
58          boundary = "aPacHeCheMIStryoPEncmiS" + Long.toHexString(action.hashCode()) + action
59                  + Long.toHexString(System.currentTimeMillis()) + Long.toHexString(this.hashCode());
60      }
61  
62      public void addParameter(String name, Object value) {
63          if (name == null || value == null) {
64              return;
65          }
66  
67          parameters.put(name, UrlBuilder.normalizeParameter(value));
68      }
69  
70      public void addPropertiesParameters(Properties properties) {
71          if (properties == null) {
72              return;
73          }
74  
75          int idx = 0;
76          for (PropertyData<?> prop : properties.getPropertyList()) {
77              if (prop == null) {
78                  continue;
79              }
80  
81              String idxStr = "[" + idx + "]";
82              addParameter(Constants.CONTROL_PROP_ID + idxStr, prop.getId());
83  
84              if (prop.getValues() != null && prop.getValues().size() > 0) {
85                  if (prop.getValues().size() == 1) {
86                      addParameter(Constants.CONTROL_PROP_VALUE + idxStr, convertPropertyValue(prop.getFirstValue()));
87                  } else {
88                      int vidx = 0;
89                      for (Object obj : prop.getValues()) {
90                          String vidxStr = "[" + vidx + "]";
91                          addParameter(Constants.CONTROL_PROP_VALUE + idxStr + vidxStr, convertPropertyValue(obj));
92                          vidx++;
93                      }
94                  }
95              }
96  
97              idx++;
98          }
99      }
100 
101     public void addPoliciesParameters(List<String> policies) {
102         if (policies == null) {
103             return;
104         }
105 
106         int idx = 0;
107         for (String policy : policies) {
108             if (policy != null) {
109                 String idxStr = "[" + idx + "]";
110                 addParameter(Constants.CONTROL_POLICY + idxStr, policy);
111                 idx++;
112             }
113         }
114     }
115 
116     public void addAddAcesParameters(Acl acl) {
117         addAcesParameters(acl, Constants.CONTROL_ADD_ACE_PRINCIPAL, Constants.CONTROL_ADD_ACE_PERMISSION);
118     }
119 
120     public void addRemoveAcesParameters(Acl acl) {
121         addAcesParameters(acl, Constants.CONTROL_REMOVE_ACE_PRINCIPAL, Constants.CONTROL_REMOVE_ACE_PERMISSION);
122     }
123 
124     private void addAcesParameters(Acl acl, String principalControl, String permissionControl) {
125         if (acl == null || acl.getAces() != null) {
126             return;
127         }
128 
129         int idx = 0;
130         for (Ace ace : acl.getAces()) {
131             if (ace.getPrincipalId() != null && ace.getPermissions() != null && !ace.getPermissions().isEmpty()) {
132                 String idxStr = "[" + idx + "]";
133                 addParameter(principalControl + idxStr, ace.getPrincipalId());
134 
135                 int permIdx = 0;
136                 for (String perm : ace.getPermissions()) {
137                     if (perm != null) {
138                         String permIdxStr = "[" + permIdx + "]";
139                         addParameter(permissionControl + idxStr + permIdxStr, perm);
140                         permIdx++;
141                     }
142                 }
143                 idx++;
144             }
145         }
146     }
147 
148     private String convertPropertyValue(Object value) {
149         if (value == null) {
150             return null;
151         }
152 
153         if (value instanceof GregorianCalendar) {
154             return "" + ((GregorianCalendar) value).getTimeInMillis();
155         }
156 
157         return value.toString();
158     }
159 
160     public String getContentType() {
161         return (contentStream == null ? CONTENT_TYPE_URLENCODED : CONTENT_TYPE_FORMDATA + boundary);
162     }
163 
164     public void write(OutputStream out) throws Exception {
165         if (contentStream == null || contentStream.getStream() == null) {
166             boolean first = true;
167             byte[] amp = "&".getBytes("UTF-8");
168 
169             for (Map.Entry<String, String> param : parameters.entrySet()) {
170                 if (first) {
171                     first = false;
172                 } else {
173                     out.write(amp);
174                 }
175 
176                 out.write((param.getKey() + "=" + URLEncoder.encode(param.getValue(), "UTF-8")).getBytes("UTF-8"));
177             }
178         } else {
179             // parameters
180             for (Map.Entry<String, String> param : parameters.entrySet()) {
181                 writeLine(out, "--" + boundary);
182                 writeLine(out, "Content-Disposition: form-data; name=\"" + param.getKey() + "\"");
183                 writeLine(out, "Content-Type: text/plain; charset=utf-8");
184                 writeLine(out);
185                 writeLine(out, param.getValue());
186             }
187 
188             // content
189             String filename = contentStream.getFileName();
190             if (filename == null || filename.length() == 0) {
191                 filename = "content";
192             }
193 
194             String mediaType = contentStream.getMimeType();
195             if (mediaType == null || mediaType.indexOf('/') < 1 || mediaType.indexOf('\n') > -1
196                     || mediaType.indexOf('\r') > -1) {
197                 mediaType = Constants.MEDIATYPE_OCTETSTREAM;
198             }
199 
200             writeLine(out, "--" + boundary);
201             writeLine(
202                     out,
203                     "Content-Disposition: "
204                             + MimeHelper.encodeContentDisposition(MimeHelper.DISPOSITION_FORM_DATA_CONTENT, filename));
205             writeLine(out, "Content-Type: " + mediaType);
206             writeLine(out, "Content-Transfer-Encoding: binary");
207             writeLine(out);
208 
209             InputStream stream = contentStream.getStream();
210             if (!(stream instanceof BufferedInputStream) && !(stream instanceof ByteArrayInputStream)) {
211                 // avoid double buffering
212                 stream = new BufferedInputStream(stream, BUFFER_SIZE);
213             }
214 
215             byte[] buffer = new byte[BUFFER_SIZE];
216             int b;
217             while ((b = stream.read(buffer)) > -1) {
218                 if (b > 0) {
219                     out.write(buffer, 0, b);
220                 }
221             }
222 
223             writeLine(out);
224             writeLine(out, "--" + boundary + "--");
225 
226             stream.close();
227         }
228     }
229 
230     private void writeLine(OutputStream out) throws Exception {
231         writeLine(out, null);
232     }
233 
234     private void writeLine(OutputStream out, String s) throws Exception {
235         s = (s == null ? CRLF : s + CRLF);
236         out.write(s.getBytes("UTF-8"));
237     }
238 }