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 
215             if (document != null) {
216                 document.setUuid(fileNode.getIdentifier());
217             }
218         }
219         catch (Exception e) {
220             throw new OleDocStoreException("File node cannot be created.", e);
221         }
222         return fileNode;
223     }
224 
225     public synchronized Node createContentNode(Node fileNode, RequestDocument document, Node parentNode,
226                                                Session session) throws OleDocStoreException {
227         Node resNode = null;
228         try {
229 
230             resNode = fileNode.addNode("jcr:content", "nt:resource");
231             resNode.setProperty("jcr:mimeType", "application/xml");
232             resNode.setProperty("jcr:encoding", "");
233 
234             String charset = "UTF-8";
235             byte[] documentBytes = null;
236             try {
237                 //                String uuid = fileNode.getIdentifier();
238                 //                document.setUuid(uuid);
239                 // Content Manipulations
240                 //                if (DocFormat.MARC.isEqualTo(document.getFormat())) {
241                 //                    new WorkBibMarcContentHandler().doPreIngestContentManipulations(document, uuid);
242                 //                }
243                 //                            else if (DocFormat.OLEML.isEqualTo(document.getFormat())) {
244                 //                                  WorkInstanceDocumentManager resolver = WorkInstanceDocumentManager.getInstance();
245                 //                                    resolver.modifyDocumentContent(document, fileNode.getIdentifier(), parentNode.getIdentifier());
246                 //                                           .doInstanceOleMLContentManipulations(document, fileNode.getIdentifier(), parentNode);
247                 //                                }
248 
249                 if (document.getContent() != null && document.getContent().getContent() != null) {
250                     documentBytes = document.getContent().getContent().getBytes();
251                 }
252 
253                 else if (document.getDocumentName() != null) {
254                     File file = new File(document.getDocumentName());
255                     if (file.exists()) {
256                         documentBytes = FileUtils.readFileToByteArray(file);
257                     }
258                 }
259             }
260             catch (Exception e) {
261                 logger.error("Failed to convert document string to byte[] with charset " + charset, e);
262             }
263             InputStream docInputStream = new ByteArrayInputStream(documentBytes);
264             Binary binary = session.getValueFactory().createBinary(docInputStream);
265             resNode.setProperty("jcr:data", binary);
266             Calendar lastModified = Calendar.getInstance();
267             lastModified.setTimeInMillis(new Date().getTime());
268             resNode.setProperty("jcr:lastModified", lastModified);
269         }
270         catch (RepositoryException e) {
271             throw new OleDocStoreException(e);
272         }
273         return resNode;
274     }
275 
276     public void enableVersioning(Node node) throws OleDocStoreException {
277         try {
278             node.addMixin("mix:versionable");
279         }
280         catch (Exception e) {
281             throw new OleDocStoreException(e);
282         }
283     }
284 
285     public Node getNodeByUUID(Session session, String uuid) throws OleDocStoreException {
286         logger.debug("Started getting node for UUID:" + uuid);
287         try {
288             return session.getNodeByIdentifier(uuid);
289         }
290         catch (RepositoryException e) {
291             throw new OleDocStoreException("getNodeByUUID failed", e);
292         }
293     }
294 
295     public String getData(Node nodeByUUID) throws OleDocStoreException, RepositoryException, FileNotFoundException {
296         StringBuffer stringBuffer = new StringBuffer();
297         if (null != nodeByUUID) {
298             Node jcrContent = nodeByUUID.getNode("jcr:content");
299             Binary binary = jcrContent.getProperty("jcr:data").getBinary();
300             InputStream content = binary.getStream();
301 
302             Writer writer;
303             try {
304                 writer = new StringWriter();
305                 char[] buffer = new char[1024];
306                 try {
307                     Reader reader = new BufferedReader(new InputStreamReader(content, "UTF-8"));
308                     int n;
309                     while ((n = reader.read(buffer)) != -1) {
310                         writer.write(buffer, 0, n);
311                     }
312                 }
313                 finally {
314                     stringBuffer.append(writer.toString());
315                     content.close();
316                 }
317 
318             }
319             catch (IOException e) {
320                 logger.info("failure during checkOut of ", e);
321             }
322 
323         }
324 
325         return stringBuffer.toString();
326     }
327 
328     public byte[] getBinaryData(Node nodeByUUID) throws RepositoryException, IOException {
329         byte[] bytes = null;
330         if (null != nodeByUUID) {
331             Node jcrContent = nodeByUUID.getNode("jcr:content");
332             Binary binary = jcrContent.getProperty("jcr:data").getBinary();
333             InputStream inputStream = binary.getStream();
334             bytes = getBytesFromInputStream(inputStream);
335         }
336         return bytes;
337     }
338 
339     public byte[] getBytesFromInputStream(InputStream is) throws IOException {
340         long length = is.available();
341         if (length > Integer.MAX_VALUE) {
342             // File is too large
343         }
344         byte[] bytes = new byte[(int) length];
345         // Read in the bytes
346         int offset = 0;
347         int numRead = 0;
348         while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
349             offset += numRead;
350         }
351         // Ensure all the bytes have been read in
352         if (offset < bytes.length) {
353             throw new IOException("Could not completely read file ");
354         }
355         // Close the input stream and return bytes
356         is.close();
357         return bytes;
358     }
359 
360 }