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