View Javadoc

1   package org.kuali.ole.docstore.repository;
2   
3   import org.apache.commons.io.FileUtils;
4   import org.kuali.ole.RepositoryManager;
5   import org.kuali.ole.docstore.OleDocStoreException;
6   import org.kuali.ole.docstore.model.enums.DocFormat;
7   import org.kuali.ole.docstore.model.xmlpojo.ingest.AdditionalAttributes;
8   import org.kuali.ole.docstore.model.xmlpojo.ingest.RequestDocument;
9   import org.kuali.ole.pojo.OleException;
10  import org.kuali.ole.repository.NodeHandler;
11  import org.slf4j.Logger;
12  import org.slf4j.LoggerFactory;
13  
14  import javax.jcr.*;
15  import java.io.*;
16  import java.util.Calendar;
17  import java.util.Collection;
18  import java.util.Date;
19  import java.util.Iterator;
20  
21  import static org.kuali.ole.docstore.process.ProcessParameters.*;
22  
23  /**
24   * Implements custom way of creating levels and nodes.
25   *
26   * @author tirumalesh.b
27   * @version %I%, %G%
28   *          Date: 28/8/12 Time: 6:09 PM
29   */
30  public class CustomNodeManager
31          implements NodeManager {
32      private static final Logger            logger      = LoggerFactory.getLogger(NodeHandler.class);
33      private static       CustomNodeManager ourInstance = new CustomNodeManager();
34  
35      protected int numLevels = 3;
36  
37      public static CustomNodeManager getInstance() {
38          return ourInstance;
39      }
40  
41      public CustomNodeManager() {
42      }
43  
44      public Node getParentNode(RequestDocument requestDocument, Session session) throws OleDocStoreException {
45          Node levelNode = null;
46          try {
47              Node formatNode = getStaticFormatNode(requestDocument, session);
48              synchronized (this.getClass()) {
49                  for (int i = 1; i <= numLevels; i++) {
50                      levelNode = initLevelNode("l" + i, formatNode, false, session);
51                      formatNode = levelNode;
52                  }
53                  //                Node l1 = initLevelNode(NODE_LEVEL1, formatNode, false, session);
54                  //                Node l2 = initLevelNode(NODE_LEVEL2, l1, false, session);
55                  //                     l3 = initLevelNode(NODE_LEVEL3, l2, false, session);
56              }
57          }
58          catch (Exception e) {
59              throw new OleDocStoreException(e);
60          }
61          return levelNode;
62      }
63  
64  
65      @Override
66      public void linkNodes(Node node, Node linkedDocumentNode, Session session) throws OleDocStoreException {
67      }
68  
69      public Node getStaticFormatNode(RequestDocument doc, Session session) throws RepositoryException {
70          Node root = session.getRootNode();
71          Node categoryNode = initStaticNode(doc.getCategory(), root, session);
72          Node typeNode = initStaticNode(doc.getType(), categoryNode, session);
73          Node formatNode = initStaticNode(doc.getFormat(), typeNode, session);
74          return formatNode;
75      }
76  
77      public Node initStaticNode(String nodeName, Node parentNode, Session session) throws RepositoryException {
78          Node node;
79          if (!parentNode.hasNode(nodeName)) {
80              synchronized (session) {
81                  node = parentNode.addNode(nodeName, "nt:unstructured");
82                  node.setProperty("nodeType", "folder");
83                  node.addMixin("mix:referenceable");
84                  session.save();
85              }
86          }
87          else {
88              node = parentNode.getNode(nodeName);
89          }
90          return node;
91      }
92  
93      public Node initNonStaticNode(String nodeName, Node parentNode) throws RepositoryException {
94          Node node;
95          node = parentNode.addNode(nodeName, "nt:unstructured");
96          node.setProperty("nodeType", "folder");
97          node.addMixin("mix:referenceable");
98          return node;
99      }
100 
101     protected void modifyAdditionalAttributes(AdditionalAttributes additionalAttributes,
102                                               RequestDocument requestDocument) {
103     }
104 
105     public synchronized Node initLevelNode(String name, Node parent, boolean isRecursiveCall, Session session)
106             throws Exception {
107         long existing = 0;
108         try {
109             long bucketSize = BUCKET_SIZES.get(name);
110             boolean hasRepeatedChild = HAS_REPEATED_CHILD.get(name);
111             if (parent.hasNode(name)) {
112                 NodeIterator existingNodes = parent.getNodes(name);
113                 existing = existingNodes.getSize();
114                 if (existing <= bucketSize && !((isRecursiveCall && existing == bucketSize) || (!hasRepeatedChild
115                                                                                                 && existing
116                                                                                                    == bucketSize))) {
117                     if (hasRepeatedChild && !isRecursiveCall) {
118                         existingNodes.skip(existing - 1);
119                         return existingNodes.nextNode();
120                     }
121                     else {
122                         Node levelNode = initNonStaticNode(name, parent);
123                         if (existing == 0) {
124                             session.save();
125                         }
126                         return levelNode;
127                     }
128                 }
129                 else {
130                     if (!STATIC_NODES.contains(parent.getPath())) {
131                         parent = initLevelNode(parent.getName(), parent.getParent(), true, session);
132                         return initNonStaticNode(name, parent);
133                     }
134                     else {
135                         throw new Exception("Node [" + parent.getName() + "/" + name + "[" + (existing + 1)
136                                             + "]] Cannot Be Created. CAUSE: TREE [" + bucketSize + "] FULL ");
137                     }
138                 }
139             }
140             else {
141                 return initNonStaticNode(name, parent);
142             }
143         }
144         catch (Exception e) {
145             try {
146                 logger.error(
147                         "Exception While initializing Node: " + parent.getName() + "/" + name + "[" + (existing + 1)
148                         + "] \t to Parent: " + parent.getName(), e);
149             }
150             catch (RepositoryException e1) {
151             }
152             throw e;
153         }
154     }
155 
156     public synchronized Node initFileNode(RequestDocument document, String name, Node parentNode, Session session)
157             throws Exception {
158         String uuid = null;
159         Node fileNode = createFileNode(document, name, parentNode, session);
160         //        Node contentNode = createContentNode(fileNode, document, parentNode, session);
161         return fileNode;
162     }
163 
164     public synchronized Node createFileNode(RequestDocument document, String name, Node parentNode, Session session)
165             throws OleDocStoreException {
166         Node fileNode = null;
167         try {
168             NodeIterator nodes = parentNode.getNodes(name);
169             if (nodes.getSize() >= BUCKET_SIZE_FILE_NODES) {
170                 if (document != null && DocFormat.OLEML.isEqualTo(document.getFormat())) {
171                     throw new RuntimeException("FileNode creation failed as the BUCKET_SIZE[" + BUCKET_SIZE_FILE_NODES
172                                                + "] is FULL: for the doc: " + document.getFormat() + "\n@ level: "
173                                                + parentNode.getPath() + "/" + name + "[" + (nodes.getSize() + 1) + "]");
174                 }
175                 else {
176                     parentNode = initLevelNode(parentNode.getName(), parentNode.getParent(), true, session);
177                 }
178             }
179 
180             fileNode = parentNode.addNode(name, "olefile");
181             fileNode.addMixin("mix:referenceable");
182             //            if (isVersioningEnabled()) {
183             //                fileNode.addMixin("mix:versionable");
184             //            }
185             //            if (DocType.LICENSE.isEqualTo(document.getType())) {
186             //                fileNode.addMixin("mix:versionable");
187             //            }
188 
189             AdditionalAttributes additionalAttributes = document.getAdditionalAttributes();
190             //            if (DocType.LICENSE.isEqualTo(document.getType()) && !DocFormat.ONIXPL.isEqualTo(document.getFormat())) {
191             //                String docName = new File(document.getDocumentName()).getName();
192             //                additionalAttributes.setAttribute("dateLoaded", Calendar.getInstance().toString());
193             //                additionalAttributes.setAttribute("fileName", docName);
194             //                additionalAttributes.setAttribute("owner", document.getUser());
195             //            }
196 
197             //modifyAdditionalAttributes(additionalAttributes, document);
198 
199             if (additionalAttributes != null) {
200                 Collection<String> attributeNames = additionalAttributes.getAttributeNames();
201                 if (attributeNames != null && attributeNames.size() > 0) {
202                     for (Iterator<String> iterator = attributeNames.iterator(); iterator.hasNext(); ) {
203                         String attributeName = iterator.next();
204                         String attributeValue = additionalAttributes.getAttribute(attributeName);
205                         fileNode.setProperty(attributeName, attributeValue);
206                     }
207                 }
208 
209             }
210             else {
211                 fileNode.setProperty("dateEntered", Calendar.getInstance());
212                 fileNode.setProperty("lastUpdated", Calendar.getInstance());
213             }
214             if (document != null) {
215                 document.setUuid(fileNode.getIdentifier());
216             }
217         }
218         catch (Exception e) {
219             throw new OleDocStoreException("File node cannot be created.", e);
220         }
221         return fileNode;
222     }
223 
224     public synchronized Node createContentNode(Node fileNode, RequestDocument document, Node parentNode,
225                                                Session session) throws OleDocStoreException {
226         Node resNode = null;
227         try {
228 
229             resNode = fileNode.addNode("jcr:content", "nt:resource");
230             resNode.setProperty("jcr:mimeType", "application/xml");
231             resNode.setProperty("jcr:encoding", "");
232 
233             String charset = "UTF-8";
234             byte[] documentBytes = null;
235             try {
236                 //                String uuid = fileNode.getIdentifier();
237                 //                document.setUuid(uuid);
238                 // Content Manipulations
239                 //                if (DocFormat.MARC.isEqualTo(document.getFormat())) {
240                 //                    new WorkBibMarcContentHandler().doPreIngestContentManipulations(document, uuid);
241                 //                }
242                 //                            else if (DocFormat.OLEML.isEqualTo(document.getFormat())) {
243                 //                                  WorkInstanceDocumentManager resolver = WorkInstanceDocumentManager.getInstance();
244                 //                                    resolver.modifyDocumentContent(document, fileNode.getIdentifier(), parentNode.getIdentifier());
245                 //                                           .doInstanceOleMLContentManipulations(document, fileNode.getIdentifier(), parentNode);
246                 //                                }
247 
248                 if (document.getContent() != null && document.getContent().getContent() != null) {
249                     documentBytes = document.getContent().getContent().getBytes();
250                 }
251 
252                 else if (document.getDocumentName() != null) {
253                     File file = new File(document.getDocumentName());
254                     if (file.exists()) {
255                         documentBytes = FileUtils.readFileToByteArray(file);
256                     }
257                 }
258             }
259             catch (Exception e) {
260                 logger.error("Failed to convert document string to byte[] with charset " + charset, e);
261             }
262             InputStream docInputStream = new ByteArrayInputStream(documentBytes);
263             Binary binary = session.getValueFactory().createBinary(docInputStream);
264             resNode.setProperty("jcr:data", binary);
265             Calendar lastModified = Calendar.getInstance();
266             lastModified.setTimeInMillis(new Date().getTime());
267             resNode.setProperty("jcr:lastModified", lastModified);
268         }
269         catch (RepositoryException e) {
270             throw new OleDocStoreException(e);
271         }
272         return resNode;
273     }
274 
275     public void enableVersioning(Node node) throws OleDocStoreException {
276         try {
277             node.addMixin("mix:versionable");
278         }
279         catch (Exception e) {
280             throw new OleDocStoreException(e);
281         }
282     }
283 
284     public Node getNodeByUUID(Session session, String uuid) throws OleDocStoreException {
285         logger.debug("Started getting node for UUID:" + uuid);
286         try {
287             return session.getNodeByIdentifier(uuid);
288         }
289         catch (RepositoryException e) {
290             throw new OleDocStoreException("getNodeByUUID failed", e);
291         }
292     }
293 
294     public String getData(Node nodeByUUID) throws OleDocStoreException, RepositoryException, FileNotFoundException {
295         StringBuffer stringBuffer = new StringBuffer();
296         if (null != nodeByUUID) {
297             Node jcrContent = nodeByUUID.getNode("jcr:content");
298             Binary binary = jcrContent.getProperty("jcr:data").getBinary();
299             InputStream content = binary.getStream();
300 
301             Writer writer;
302             try {
303                 writer = new StringWriter();
304                 char[] buffer = new char[1024];
305                 try {
306                     Reader reader = new BufferedReader(new InputStreamReader(content, "UTF-8"));
307                     int n;
308                     while ((n = reader.read(buffer)) != -1) {
309                         writer.write(buffer, 0, n);
310                     }
311                 }
312                 finally {
313                     stringBuffer.append(writer.toString());
314                     content.close();
315                 }
316 
317             }
318             catch (IOException e) {
319                 logger.info("failure during checkOut of ", e);
320             }
321 
322         }
323 
324         return stringBuffer.toString();
325     }
326 
327     public byte[] getBinaryData(Node nodeByUUID) throws RepositoryException, IOException {
328         byte[] bytes = null;
329         if (null != nodeByUUID) {
330             Node jcrContent = nodeByUUID.getNode("jcr:content");
331             Binary binary = jcrContent.getProperty("jcr:data").getBinary();
332             InputStream inputStream = binary.getStream();
333             bytes = getBytesFromInputStream(inputStream);
334         }
335         return bytes;
336     }
337 
338     public byte[] getBytesFromInputStream(InputStream is) throws IOException {
339         long length = is.available();
340         if (length > Integer.MAX_VALUE) {
341             // File is too large
342         }
343         byte[] bytes = new byte[(int) length];
344         // Read in the bytes
345         int offset = 0;
346         int numRead = 0;
347         while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
348             offset += numRead;
349         }
350         // Ensure all the bytes have been read in
351         if (offset < bytes.length) {
352             throw new IOException("Could not completely read file ");
353         }
354         // Close the input stream and return bytes
355         is.close();
356         return bytes;
357     }
358 
359 }