This project has retired. For details please refer to its Attic page.
Main 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.specexamples;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.File;
24  import java.io.FileFilter;
25  import java.io.FileInputStream;
26  import java.io.FileOutputStream;
27  import java.io.IOException;
28  import java.math.BigInteger;
29  import java.util.ArrayList;
30  import java.util.Collections;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
34  import java.util.zip.ZipEntry;
35  import java.util.zip.ZipOutputStream;
36  
37  import org.apache.chemistry.opencmis.client.bindings.CmisBindingFactory;
38  import org.apache.chemistry.opencmis.commons.PropertyIds;
39  import org.apache.chemistry.opencmis.commons.SessionParameter;
40  import org.apache.chemistry.opencmis.commons.data.Ace;
41  import org.apache.chemistry.opencmis.commons.data.Acl;
42  import org.apache.chemistry.opencmis.commons.data.CmisExtensionElement;
43  import org.apache.chemistry.opencmis.commons.data.ContentStream;
44  import org.apache.chemistry.opencmis.commons.data.ExtensionsData;
45  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderData;
46  import org.apache.chemistry.opencmis.commons.data.ObjectInFolderList;
47  import org.apache.chemistry.opencmis.commons.data.Properties;
48  import org.apache.chemistry.opencmis.commons.data.PropertyData;
49  import org.apache.chemistry.opencmis.commons.data.RepositoryInfo;
50  import org.apache.chemistry.opencmis.commons.enums.AclPropagation;
51  import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
52  import org.apache.chemistry.opencmis.commons.enums.BindingType;
53  import org.apache.chemistry.opencmis.commons.enums.IncludeRelationships;
54  import org.apache.chemistry.opencmis.commons.enums.VersioningState;
55  import org.apache.chemistry.opencmis.commons.impl.dataobjects.BindingsObjectFactoryImpl;
56  import org.apache.chemistry.opencmis.commons.impl.dataobjects.CmisExtensionElementImpl;
57  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
58  import org.apache.chemistry.opencmis.commons.impl.dataobjects.ExtensionDataImpl;
59  import org.apache.chemistry.opencmis.commons.spi.AclService;
60  import org.apache.chemistry.opencmis.commons.spi.BindingsObjectFactory;
61  import org.apache.chemistry.opencmis.commons.spi.CmisBinding;
62  import org.apache.chemistry.opencmis.commons.spi.DiscoveryService;
63  import org.apache.chemistry.opencmis.commons.spi.Holder;
64  import org.apache.chemistry.opencmis.commons.spi.MultiFilingService;
65  import org.apache.chemistry.opencmis.commons.spi.NavigationService;
66  import org.apache.chemistry.opencmis.commons.spi.ObjectService;
67  import org.apache.chemistry.opencmis.commons.spi.RepositoryService;
68  import org.apache.chemistry.opencmis.commons.spi.VersioningService;
69  import org.apache.commons.io.filefilter.WildcardFileFilter;
70  import org.apache.commons.logging.Log;
71  import org.apache.commons.logging.LogFactory;
72  
73  public class Main {
74  
75      private static final Log LOG = LogFactory.getLog(Main.class.getName());
76      private static final BigInteger TYPE_DEPTH_ALL = BigInteger.valueOf(-1);
77      private static final BigInteger MAX_ITEMS = null;
78      private static final BigInteger SKIP_COUNT = BigInteger.valueOf(0);
79      private static final String TOPLEVEL_TYPE = "DocumentTopLevel";
80      private static final String VERSIONED_TYPE = "VersionableType";
81      private static final String VERSIONED_PROP = "VersionedStringProp";
82      private static String LOGDIR = System.getProperty("java.io.tmpdir");// + File.separator;
83      private String targetDir = System.getProperty("java.io.tmpdir");// + File.separator;
84  
85      private BindingsObjectFactory objFactory = new BindingsObjectFactoryImpl();
86      private BindingType bindingType;
87      private String rootFolderId;
88      private String repositoryId;
89      private ObjectService objSvc;
90      private NavigationService navSvc;
91      private RepositoryService repSvc;
92      private VersioningService verSvc;
93      private MultiFilingService multiSvc;
94      private DiscoveryService discSvc;
95      private AclService aclSvc;
96  
97      private static final String[] URLS = {"http://localhost:8080/inmemory/atom", 
98              "http://localhost:8080/inmemory/services", 
99              "http://localhost:8080/inmemory/browser"};
100     private static final BindingType[] BINDINGS = {BindingType.ATOMPUB, BindingType.WEBSERVICES, BindingType.BROWSER};
101 
102     public Main() {
103     }
104 
105     public void runAllBindings() {
106       for (int i = 0; i < BINDINGS.length; i++) {
107             bindingType = BINDINGS[i];
108             init(URLS[i], BINDINGS[i]);
109             run();
110         }
111         
112     }
113     
114     public void run() {
115         LOG.debug("Generating spec examples for Binding: " + bindingType.value());
116         // Repository Service:
117         getRepositories();
118 
119         repositoryId = "A1";
120         getRepositoryInfo();
121 
122         getTypeDefinition("cmis:folder");
123         
124         String docId = getTestDocId();
125         String folderId = getTestFolderId();
126 
127         getTypeChildren(TOPLEVEL_TYPE);
128 
129         // Navigation Service:
130         getChildren(folderId);
131         getDescendants(folderId);
132 
133         // Object Service:
134         getObject(docId);
135         getAcl(docId);
136         String id1 = createDocument("SampleDocument", TOPLEVEL_TYPE, rootFolderId, VersioningState.NONE);
137         updateProperties(id1, PropertyIds.NAME, "RenamedDocument");
138         getAllowableActions(id1);
139         
140         deleteObject(id1);
141 
142         // Discovery Service:
143         doQuery();
144 
145         // Versioning Service
146         String id2 = prepareVersionSeries("VersionedDocument", VERSIONED_TYPE, rootFolderId);
147         checkOut(id2);
148         checkIn(id2, true, "final version in series");
149         getAllVersions(id2);
150 
151         // delete all generated objects
152         String[] ids = {id2};
153         
154         cleanup(ids);
155 
156         // collect all captured files and store them in a ZIP file
157         String dirs[] = {BindingType.ATOMPUB.value(), BindingType.WEBSERVICES.value(), BindingType.BROWSER.value() };        
158         createZipFile("CMIS-Spec-Examples.zip", dirs);
159     }
160 
161     private void init(String url, BindingType bindingType) {
162         LOG.debug("Initializing connection to InMemory server: ");
163         LOG.debug("   Binding: " + bindingType.value());
164         LOG.debug("   URL: " + url);
165 
166         Map<String, String> parameters = new HashMap<String, String>();
167         parameters.put(SessionParameter.USER, "admin");
168         parameters.put(SessionParameter.PASSWORD, "admin");
169 
170         parameters.put(SessionParameter.BINDING_TYPE, bindingType.value());
171 
172         // get factory and create binding
173         CmisBindingFactory factory = CmisBindingFactory.newInstance();
174         CmisBinding binding = null;
175         
176         if (bindingType == BindingType.ATOMPUB)  {
177             parameters.put(SessionParameter.ATOMPUB_URL, url);
178             binding = factory.createCmisAtomPubBinding(parameters);
179         } else if (bindingType == BindingType.WEBSERVICES) {
180             parameters.put(SessionParameter.WEBSERVICES_ACL_SERVICE, url + "/ACLService?wsdl");
181             parameters.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE,  url + "/DiscoveryService?wsdl");
182             parameters.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE,  url + "/MultiFilingService?wsdl");
183             parameters.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE,  url + "/NavigationService?wsdl");
184             parameters.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE,  url + "/ObjectService?wsdl");
185             parameters.put(SessionParameter.WEBSERVICES_POLICY_SERVICE,  url + "/PolicyService?wsdl");
186             parameters.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE,  url + "/RelatinshipService?wsdl");
187             parameters.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE,  url + "/RepositoryService?wsdl");
188             parameters.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE,  url + "/VersioningService?wsdl");
189             binding = factory.createCmisWebServicesBinding(parameters);            
190         } else if (bindingType == BindingType.BROWSER) {
191             parameters.put(SessionParameter.BROWSER_URL, url); 
192             binding = factory.createCmisBrowserBinding(parameters);            
193         } else {
194             LOG.error("Unknown binding type: " + bindingType.value());
195             return;
196         }
197         objFactory = binding.getObjectFactory();
198         repSvc = binding.getRepositoryService();
199         objSvc = binding.getObjectService();
200         navSvc = binding.getNavigationService();
201         verSvc = binding.getVersioningService();
202         multiSvc = binding.getMultiFilingService();
203         discSvc = binding.getDiscoveryService();
204         aclSvc = binding.getAclService();
205         
206         // create a folder where target files will be stored:
207         targetDir = bindingType.value();
208         File in = new File(targetDir);
209         boolean ok = in.mkdir();
210         
211         LOG.debug("creating target directory for files: " + ok);
212         LOG.debug("Initializing done. ");
213     }
214 
215     private void getRepositories() {
216         LOG.debug("getRepositories()");
217         List<RepositoryInfo> repositories = repSvc.getRepositoryInfos(null);
218         this.repositoryId = repositories.get(0).getId();
219         renameFiles("getRepositoryInfos");
220         LOG.debug("getRepositoryInfo() done.");
221     }
222 
223     private void getRepositoryInfo() {
224         LOG.debug("getting repository info for repository " + repositoryId);
225         // Because the browser binding silently retrieves all repositories on the first request we call it twice
226         // and use a dummy extension data element to prevent caching
227         RepositoryInfo repoInfo = repSvc.getRepositoryInfo(repositoryId, null);
228         if (bindingType.equals(BindingType.BROWSER)) {
229             ExtensionDataImpl dummyExt = new ExtensionDataImpl();
230             List<CmisExtensionElement> extList = new ArrayList<CmisExtensionElement>() {{ add(new CmisExtensionElementImpl("foo", "foo", null, "bar")); }};
231             dummyExt.setExtensions(extList);
232             repoInfo = repSvc.getRepositoryInfo(repositoryId, dummyExt);
233         }
234         LOG.debug("repository id is: " + repoInfo.getId());
235         rootFolderId = repoInfo.getRootFolderId();
236         LOG.debug("root folder id is: " + repoInfo.getRootFolderId());
237         renameFiles("getRepositoryInfo");
238         LOG.debug("getRepositoryInfo() done.");
239     }
240 
241     private void getObject(String objectId) {
242         LOG.debug("getObject " + objectId);
243         objSvc.getObject(repositoryId, objectId, "*", true /* includeAllowableActions */,
244                 IncludeRelationships.NONE /* includeRelationships */, null /* renditionFilter */,
245                 false /* includePolicyIds */, true /* includeAcl */, null);
246         renameFiles("getObject");
247         LOG.debug("getObject() done.");
248     }
249 
250     private void getChildren(String folderId) {
251         LOG.debug("getChildren " + folderId);
252         navSvc.getChildren(repositoryId, folderId, "*", null /* orderBy */, true /* includeAllowableActions */,
253                 IncludeRelationships.NONE, null /* renditionFilter */, true /* includePathSegment */, MAX_ITEMS,
254                 SKIP_COUNT, null);
255         renameFiles("getChildren");
256         LOG.debug("getChildren() done.");
257     }
258 
259     private void getDescendants(String folderId) {
260         final BigInteger DEPTH = BigInteger.valueOf(3);
261         LOG.debug("getDescendants " + folderId);
262         navSvc.getDescendants(repositoryId, folderId, DEPTH, "*", true /* includeAllowableActions */,
263                 IncludeRelationships.NONE, null /* renditionFilter */, true /* includePathSegment */, null);
264         renameFiles("getDescendants");
265         LOG.debug("getDescendants() done.");
266     }
267 
268     private void doQuery() {
269         LOG.debug("doQuery ");
270         String statement = "SELECT * from cmis:document WHERE IN_FOLDER('" + rootFolderId + "')";
271         discSvc.query(repositoryId, statement, false /* searchAllVersions */, true /* includeAllowableActions */,
272                 IncludeRelationships.NONE, null, MAX_ITEMS, SKIP_COUNT, null);
273         renameFiles("doQuery");
274         LOG.debug("doQuery() done.");
275     }
276 
277     private void getTypeChildren(String typeId) {
278         LOG.debug("getTypeChildren " + typeId);
279         repSvc.getTypeChildren(repositoryId, typeId, true /* includePropertyDefinitions */, MAX_ITEMS, SKIP_COUNT, null);
280         renameFiles("getTypeChildren");
281         LOG.debug("getTypeChildren() done.");
282     }
283 
284     private String createDocument(String name, String typeId, String folderId, VersioningState versioningState) {
285         LOG.debug("createDocument " + typeId);
286 
287         String id = createDocumentIntern(name, typeId, folderId, versioningState);
288         renameFiles("createDocument");
289         LOG.debug("createDocument() done.");
290 
291         return id;
292     }
293 
294     private String createDocumentIntern(String name, String typeId, String folderId, VersioningState versioningState) {
295         ContentStream contentStream = null;
296         List<String> policies = null;
297         Acl addACEs = null;
298         Acl removeACEs = null;
299         ExtensionsData extension = null;
300 
301         List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
302         properties.add(objFactory.createPropertyIdData(PropertyIds.NAME, name));
303         properties.add(objFactory.createPropertyIdData(PropertyIds.OBJECT_TYPE_ID, typeId));
304         Properties props = objFactory.createPropertiesData(properties);
305 
306         contentStream = createContent();
307 
308         String id = null;
309         id = objSvc.createDocument(repositoryId, props, folderId, contentStream, versioningState, policies, addACEs,
310                 removeACEs, extension);
311         return id;
312     }
313 
314     private ContentStream createContent() {
315         ContentStreamImpl content = new ContentStreamImpl();
316         content.setFileName("data.txt");
317         content.setMimeType("text/plain");
318         int len = 32 * 1024;
319         byte[] b = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a,
320                 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x0c, 0x0a }; // 32
321         // Bytes
322         ByteArrayOutputStream ba = new ByteArrayOutputStream(len);
323         try {
324             for (int i = 0; i < 1024; i++) {
325                 ba.write(b);
326             }
327         } catch (IOException e) {
328             throw new RuntimeException("Failed to fill content stream with data", e);
329         }
330         content.setStream(new ByteArrayInputStream(ba.toByteArray()));
331         content.setLength(BigInteger.valueOf(len));
332         return content;
333     }
334 
335     private void updateProperties(String id, String propertyId, String propertyValue) {
336         LOG.debug("updateProperties " + id);
337         List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
338         properties.add(objFactory.createPropertyStringData(propertyId, propertyValue));
339         Properties newProps = objFactory.createPropertiesData(properties);
340 
341         Holder<String> idHolder = new Holder<String>(id);
342         Holder<String> changeTokenHolder = new Holder<String>();
343         objSvc.updateProperties(repositoryId, idHolder, changeTokenHolder, newProps, null);
344         renameFiles("updateProperties");
345         LOG.debug("updateProperties() done.");
346     }
347 
348     private void deleteObject(String id) {
349         LOG.debug("deleteObject " + id);
350         objSvc.deleteObject(repositoryId, id, true, null);
351         renameFiles("deleteObject");
352         LOG.debug("deleteObject() done.");
353     }
354 
355     private void cleanup (String[] ids) {
356         LOG.debug("cleaning up...");
357         for (String id : ids) {
358             LOG.debug("deleteing object " + id);
359             objSvc.deleteObject(repositoryId, id, true, null);            
360         }
361         LOG.debug("... cleaning up done");
362     }
363     
364     /**
365      * enumerate the children of the root folder and return the id of the first
366      * document
367      * 
368      * @return id of first doc in root folder
369      */
370     private String getTestDocId() {
371         return getTestId(BaseTypeId.CMIS_DOCUMENT);
372     }
373 
374     /**
375      * enumerate the children of the root folder and return the id of the first
376      * sub-folder
377      * 
378      * @return id of first doc in root folder
379      */
380     private String getTestFolderId() {
381         return getTestId(BaseTypeId.CMIS_FOLDER);
382     }
383 
384     private String getTestId(BaseTypeId baseTypeId) {
385         LOG.debug("getTestDocId()");
386         ObjectInFolderList result = navSvc.getChildren(repositoryId, rootFolderId, "*", null, false,
387                 IncludeRelationships.NONE, null, true, MAX_ITEMS, SKIP_COUNT, null);
388 
389         List<ObjectInFolderData> children = result.getObjects();
390         LOG.debug(" found " + children.size() + " folders in getChildren()");
391         for (ObjectInFolderData child : children) {
392             if (baseTypeId.equals(child.getObject().getBaseTypeId()))
393                 return child.getObject().getId();
394         }
395         return null;
396     }
397 
398     private String prepareVersionSeries(String name, String typeId, String folderId) {
399         String id = createDocumentIntern(name, typeId, folderId, VersioningState.MAJOR);
400         Holder<Boolean> contentCopied = new Holder<Boolean>();
401         Holder<String> idHolder = new Holder<String>(id);
402 
403         verSvc.checkOut(repositoryId, idHolder, null, contentCopied);
404         String checkinComment = "Checkin V2.0";
405         verSvc.checkIn(repositoryId, idHolder, true /*major*/, null /*properties*/, null /*content*/,
406                 checkinComment, null/*policies*/, null/*addAcl*/, null /*removeAcl*/, null /*extension*/);
407 
408         verSvc.checkOut(repositoryId, idHolder, null, contentCopied);
409         checkinComment = "Checkin V2.1";
410         verSvc.checkIn(repositoryId, idHolder, false /*major*/, null /*properties*/, null /*content*/,
411                 checkinComment, null/*policies*/, null/*addAcl*/, null /*removeAcl*/, null /*extension*/);
412         
413         return idHolder.getValue();
414     }
415     
416     private void checkOut(String id) {
417         LOG.debug("checkOut()");        
418         Holder<String> idHolder = new Holder<String>(id);
419         Holder<Boolean> contentCopied = new Holder<Boolean>(true);
420         verSvc.checkOut(repositoryId, idHolder, null, contentCopied);
421         renameFiles("checkOut");
422         LOG.debug("checkOut done.");
423     }
424 
425     private void checkIn(String id, boolean major, String checkinComment) {
426         LOG.debug("checkIn()");
427         List<PropertyData<?>> properties = new ArrayList<PropertyData<?>>();
428         properties.add(objFactory.createPropertyStringData(VERSIONED_PROP, "updated value"));
429         Properties newProps = objFactory.createPropertiesData(properties);
430 
431         Holder<String> idHolder = new Holder<String>(id);
432         verSvc.checkIn(repositoryId, idHolder, major /*major*/, newProps /*properties*/, null /*content*/,
433                 checkinComment, null/*policies*/, null/*addAcl*/, null /*removeAcl*/, null /*extension*/);
434         renameFiles("checkIn");
435         LOG.debug("checkIn done.");
436     }
437 
438     private void getAllVersions(String id) {
439         LOG.debug("getAllVersions()");     
440         verSvc.getAllVersions(repositoryId, id/* object id */, id/* series id */, "*"/* filter */,
441                 false /* includeAllowableActions */, null /* extension */);
442         renameFiles("getAllVersions");
443         LOG.debug("getAllVersions done.");
444     }
445     
446     private void getAcl(String objectId) {
447         LOG.debug("getting Acl() " + objectId);
448 
449         // get old ACL first:
450         Acl oldAcl = aclSvc.getAcl(repositoryId, objectId, true, null);
451 
452         // create a new ACL for the test doc
453         List<Ace> aces = new ArrayList<Ace>();
454         aces.add(objFactory.createAccessControlEntry("Alice", Collections.singletonList("cmis:read")));
455         aces.add(objFactory.createAccessControlEntry("Bob", Collections.singletonList("cmis:write")));
456         aces.add(objFactory.createAccessControlEntry("admin", Collections.singletonList("cmis:all")));
457         Acl acl = objFactory.createAccessControlList(aces);
458 
459         // add the new ACL and remove the old one
460         aclSvc.applyAcl(repositoryId, objectId, acl, oldAcl, AclPropagation.OBJECTONLY, null);
461             
462         aclSvc.getAcl(repositoryId, objectId, true, null);
463         renameFiles("getAcl");
464         LOG.debug("getting Acl() done.");
465     }
466 
467     private void getTypeDefinition(String typeId) {
468         LOG.debug("getTypeDefinition " + typeId);
469         repSvc.getTypeDefinition(repositoryId, typeId, null);
470         renameFiles("getTypeDefinition");
471         LOG.debug("getTypeDefinition() done.");
472     }
473 
474     private void getTypeDescendants(String typeId) {
475         LOG.debug("getTypeDescendants " + typeId);
476         repSvc.getTypeDescendants(repositoryId, typeId, TYPE_DEPTH_ALL, true /* includePropertyDefinitions */, null);
477         renameFiles("getTypeDescendants");
478         LOG.debug("getTypeDescendants() done.");
479     }
480 
481     private void getAllowableActions(String objectId) {
482         LOG.debug("getAllowableActions " + objectId);
483         objSvc.getAllowableActions(repositoryId, objectId, null);
484         renameFiles("getAllowableActions");
485         LOG.debug("getAllowableActions() done.");
486     }
487 
488     private void renameFiles(String name) {
489         String fileNameInReq = findLastFile(LOGDIR, "*-request.log");
490         String fileNameInResp = findLastFile(LOGDIR, "*-response.log");
491         if (null == fileNameInReq) {
492             LOG.error("Failed to find captured request file for " + name);
493             return;
494         }
495         if (null == fileNameInResp) {
496             LOG.error("Failed to find captured response file for " + name);
497             return;
498         }
499         File in = new File(fileNameInReq);
500         File out = new File(targetDir + File.separator + name + "-request.log");
501         if (out.exists())
502             out.delete();
503         boolean ok = in.renameTo(out);
504         if (ok)
505             LOG.debug("Renaming file " + in.getAbsolutePath() + " to " + out.getAbsolutePath() + " succeeded.");
506         else
507             LOG.warn("Renaming file " + in.getAbsolutePath() + " to " + out.getAbsolutePath() + " failed.");
508 
509         in = new File(fileNameInResp);
510         out = new File(targetDir + File.separator + name + "-response.log");
511         if (out.exists())
512             out.delete();
513         ok = in.renameTo(out);
514         if (ok)
515             LOG.debug("Renaming file " + in.getAbsolutePath() + "to " + out.getAbsolutePath() + " succeeded.");
516         else
517             LOG.warn("Renaming file " + in.getAbsolutePath() + " to " + out.getAbsolutePath() + " failed.");
518     }
519     
520     private void createZipFile(String zipFileName, String[] dirs) {
521         
522         File out = new File(zipFileName);
523         if (out.exists())
524             out.delete();
525         
526         FileOutputStream fout = null;
527         ZipOutputStream zout =null;
528         try {
529             fout = new FileOutputStream(zipFileName);
530             zout = new ZipOutputStream(fout);
531             for (String dir: dirs) {
532                 File dirToZip = new File(dir);
533                 addDirectory(zout, dir, dirToZip);
534             }
535         } catch (Exception e) {
536             LOG.error("Creating ZIP file failed: " + e);
537         } finally {
538             try {
539                 if (zout != null)
540                     zout.close();
541                 if (fout != null)
542                     fout.close();
543             } catch (IOException e) {
544                 LOG.error(e);
545             }
546         }
547     }
548     
549     private static void addDirectory(ZipOutputStream zout, String prefix, File sourceDir) throws IOException {
550         
551         File[] files = sourceDir.listFiles();
552         LOG.debug("Create Zip, adding directory " + sourceDir.getName());
553                
554         if (null != files) {
555             for(int i=0; i < files.length; i++)
556             {
557                 if(files[i].isDirectory())
558                 {
559                     addDirectory(zout, prefix + File.separator + files[i].getName(), files[i]);
560                 } else {
561                     LOG.debug("Create Zip, adding file " + files[i].getName());
562                     byte[] buffer = new byte[65536];
563                     FileInputStream fin = new FileInputStream(files[i]);
564                     String zipEntryName = prefix + File.separator + files[i].getName();
565                     LOG.debug("   adding entry " + zipEntryName);
566                     zout.putNextEntry(new ZipEntry(zipEntryName));
567 
568                     int length;
569                     while((length = fin.read(buffer)) > 0)
570                     {
571                         zout.write(buffer, 0, length);
572                     }
573 
574                     zout.closeEntry();
575                     fin.close();
576                 }
577             }      
578         }
579     }
580     
581     public static void clean() {
582         LOG.debug("Cleaning generated and captured request and response logs...");
583         
584         cleanFilesWithFilter(LOGDIR, "*-request.log");
585         cleanFilesWithFilter(LOGDIR, "*-response.log");
586         for (int i = 0; i < BINDINGS.length; i++) {
587             String dir = BINDINGS[i].value();
588             
589             cleanFilesWithFilter(dir, "*-request.log");
590             cleanFilesWithFilter(dir, "*-response.log");
591 
592             File dirToDelete = new File (dir);
593             boolean ok = dirToDelete.delete();
594             if (ok)
595                 LOG.debug("Deleting dir " + dirToDelete.getAbsolutePath() + " succeeded.");
596             else
597                 LOG.warn("Deleting dir " + dirToDelete.getAbsolutePath() + " failed.");
598         }
599         LOG.debug("... done.");        
600     }
601     
602     private static void cleanFilesWithFilter(String directoryPath, String wildcardFilter) {
603         File dir = new File(directoryPath);
604         FileFilter fileFilter = new WildcardFileFilter(wildcardFilter);
605         File[] files = dir.listFiles(fileFilter);
606         if (files != null)
607             for (int i = 0; i < files.length; i++) {
608                 boolean ok = files[i].delete();
609                 LOG.debug("Deleting file: " + files[i] + ", success: " + ok);
610             }        
611     }
612     
613     private static String findLastFile(String directoryPath, String wildcardFilter) {
614         File dir = new File(directoryPath);
615         FileFilter fileFilter = new WildcardFileFilter(wildcardFilter);
616         File[] files = dir.listFiles(fileFilter);
617         if (files.length == 0)
618             return null;
619         else
620             return files[files.length-1].getAbsolutePath();
621     }
622 
623     public static void main(String[] args) {
624         if (args.length > 0 && args[0].equals("-clean")) {
625             LOG.debug("Cleaning up generated files...");
626             Main.clean();
627             LOG.debug("... cleaning up done.");
628         } else {
629             LOG.debug("Starting generating spec examples...");
630             Main main = new Main();
631             main.runAllBindings();
632             LOG.debug("... finished generating spec examples.");
633         }
634     }
635 }