View Javadoc

1   /*
2    * Copyright 2007 Hippo
3    *
4    * Licensed under the Apache License, Version 2.0 (the  "License"); 
5    * you may not use this file except in compliance with the License. 
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" 
12   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
13   * See the License for the specific language governing permissions and 
14   * limitations under the License.
15   */
16  package nl.hippo.client.webdav.binding.content;
17  
18  import java.io.IOException;
19  import java.io.InputStream;
20  import java.util.ArrayList;
21  import java.util.Iterator;
22  
23  import nl.hippo.client.api.ClientException;
24  import nl.hippo.client.api.DocumentNotFoundException;
25  import nl.hippo.client.api.CollectionNotFoundException;
26  import nl.hippo.client.api.content.Document;
27  import nl.hippo.client.api.content.DocumentCollection;
28  import nl.hippo.client.api.content.DocumentMetadata;
29  import nl.hippo.client.api.content.DocumentPath;
30  import nl.hippo.client.api.content.RawResponse;
31  import nl.hippo.client.webdav.WebdavConfig;
32  import nl.hippo.client.webdav.WebdavResponse;
33  import nl.hippo.client.webdav.caching.WebdavCacheHandler;
34  import nl.hippo.client.webdav.method.Get;
35  import nl.hippo.client.webdav.method.PropFind;
36  import nl.hippo.client.webdav.method.Search;
37  import nl.hippo.client.webdav.method.SearchDocumentById;
38  import nl.hippo.client.webdav.utils.Converters;
39  
40  import org.jibx.runtime.BindingDirectory;
41  import org.jibx.runtime.IBindingFactory;
42  import org.jibx.runtime.IUnmarshallingContext;
43  import org.jibx.runtime.JiBXException;
44  
45  /**
46   * A factory of Documents
47   */
48  public class DocumentFactory {
49  
50      private static final String SEARCHRESULT_XSLT = "resources/searchresult.xslt";
51      public static final WebdavResponse xslt;
52  
53      private static IBindingFactory searchResultXMLBindingFactory;
54      static {
55          try {
56              searchResultXMLBindingFactory = BindingDirectory.getFactory(DocumentCollectionImpl.class);
57          } catch (JiBXException e) {
58              throw new ExceptionInInitializerError("Exception while initializing DocumentBindingFactory: "
59                      + e.getMessage());
60          }
61          InputStream in = DocumentFactory.class.getResourceAsStream(SEARCHRESULT_XSLT);
62          try {
63              xslt = new WebdavResponse(Converters.stream2Bytes(in));
64          } catch (IOException e) {
65              throw new ExceptionInInitializerError("Exception while initializing searchresult transformer: "
66                      + e.getMessage());
67          }
68      }
69  
70      private WebdavConfig config;
71  
72      public DocumentFactory(WebdavConfig config) {
73          if (config == null) {
74              throw new IllegalArgumentException("DocumentFactory constructor parameter config may not be null.");
75          }
76          this.config = config;
77      }
78  
79      public Document fetchDocument(WebdavCacheHandler cache, DocumentPath docPath) throws ClientException {
80          WebdavResponse response = new PropFind(config).execute(cache, docPath);
81          Document boundDoc = bindDocument(cache, response);
82  
83          if (boundDoc == null) {
84              throw new DocumentNotFoundException("Document not found at: " + docPath.getFullPath());
85          }
86          RawResponse content = new Get(config).execute(cache, docPath);
87          return new DocumentImpl(docPath, boundDoc.getMetadata(), content);
88      }
89  
90      public DocumentMetadata fetchMetadata(WebdavCacheHandler cache, DocumentPath docPath) throws ClientException {
91          WebdavResponse response = new PropFind(config).execute(cache, docPath);
92          Document boundDoc = bindDocument(cache, response);
93          if (boundDoc == null) {
94              throw new DocumentNotFoundException("Document not found at: " + docPath.getFullPath());
95          }
96          return boundDoc.getMetadata();
97      }
98  
99      public DocumentCollection fetchCollection(WebdavCacheHandler cache, DocumentPath targetPath, InputStream dasl,
100             boolean includeContent) throws ClientException {
101         if (dasl == null) {
102             throw new IllegalArgumentException("Parameter dasl may not be null");
103         }
104         try {
105             String daslAsString = new String(Converters.stream2Bytes(dasl));
106             return fetchCollection(cache, targetPath, daslAsString, includeContent);
107 
108         } catch (IOException e) {
109             throw new ClientException("Exception while reading dasl from InputStream" + e.getMessage());
110         }
111     }
112 
113     public DocumentCollection fetchCollection(WebdavCacheHandler cache, DocumentPath targetPath, String dasl,
114             boolean includeContent) throws ClientException {
115         Search search = new Search(config);
116         WebdavResponse response = search.execute(cache, targetPath, dasl);
117         DocumentCollection result = bindSearch(cache, response);
118 
119         if (result != null && includeContent) {
120             Iterator it = result.getDocuments().iterator();
121             while (it.hasNext()) {
122                 DocumentImpl doc = (DocumentImpl) it.next();
123                 doc.content = new Get(config).execute(cache, doc.getPath());
124             }
125         }
126         
127         if (result == null) {
128             throw new CollectionNotFoundException("Collection not found at: " + targetPath.getFullPath());
129         }
130         return result;
131     }
132 
133     public DocumentPath resolvePath(WebdavCacheHandler cache, String documentId) throws ClientException {
134         DocumentPath path = new SearchDocumentById(config).execute(cache, this, documentId);
135         
136         if (path == null) {
137             throw new DocumentNotFoundException("Document not found with id: " + documentId);
138         }
139         
140         return path;
141     }
142 
143     public Document bindDocument(WebdavCacheHandler cache, WebdavResponse response) throws ClientException {
144         DocumentCollection searchResult = bindSearch(cache, response);
145         if (searchResult == null || searchResult.getDocuments() == null || searchResult.getDocuments().size() == 0) {
146             return null;
147         }
148         return (Document) searchResult.getDocuments().get(0);
149     }
150 
151     private DocumentCollection bindSearch(WebdavCacheHandler cache, WebdavResponse response) throws ClientException {
152         if (!response.isValid()) {
153             return null;
154         }
155 
156         WebdavResponse transformedResponse = response.transform(xslt, cache);
157 
158         // Unmarshal the XML to a DocumentCollection instance
159         DocumentCollection binding;
160         try {
161             IUnmarshallingContext context = searchResultXMLBindingFactory.createUnmarshallingContext();
162             binding = (DocumentCollection) context.unmarshalDocument(transformedResponse.getResponseAsStream(), null);
163         } catch (JiBXException e) {
164             throw new ClientException("Unmarshalling XML to DocumentCollection failed.", e);
165         }
166 
167         // This is a hack to set the 'path' attribute of each Document/DocumentMetadata object 
168         // in the DocumentCollection which is not set automatically by the unmarshalling.
169         // TODO: Refactor the unmarshalling so that it does set the path attribute directly and then remove this loop.
170         ArrayList documentsWithPath = new ArrayList();
171         Iterator it = binding.getDocuments().iterator();
172         while (it.hasNext()) {
173             DocumentImpl docWithoutPath = (DocumentImpl) it.next();
174             DocumentPath docPath = config.getBasePath().createAbsolutePath(docWithoutPath.tmpPath);
175             DocumentMetadataImpl metadataWithoutPath = (DocumentMetadataImpl) docWithoutPath.getMetadata();
176 
177             DocumentMetadata metadataWithPath = new DocumentMetadataImpl(metadataWithoutPath, docPath);
178             Document documentWithPath = new DocumentImpl(docPath, metadataWithPath, null);
179 
180             documentsWithPath.add(documentWithPath);
181         }
182         return new DocumentCollectionImpl(documentsWithPath);
183     }
184 
185 }