001 /* 002 * Copyright 2011 The Kuali Foundation. 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.ole.repository; 017 018 import org.apache.commons.io.FileUtils; 019 import org.kuali.ole.RepositoryManager; 020 import org.kuali.ole.docstore.DocStoreConstants; 021 import org.kuali.ole.docstore.OleDocStoreException; 022 import org.kuali.ole.docstore.model.enums.DocFormat; 023 import org.kuali.ole.docstore.model.enums.DocType; 024 import org.kuali.ole.docstore.model.xmlpojo.ingest.AdditionalAttributes; 025 import org.kuali.ole.docstore.model.xmlpojo.ingest.RequestDocument; 026 import org.kuali.ole.documenthandler.WorkBibMarcContentHandler; 027 import org.kuali.ole.documenthandler.WorkInstanceOleMLContentHandler; 028 import org.kuali.ole.pojo.OleException; 029 import org.slf4j.Logger; 030 import org.slf4j.LoggerFactory; 031 032 import javax.jcr.*; 033 import java.io.ByteArrayInputStream; 034 import java.io.File; 035 import java.io.InputStream; 036 import java.util.Calendar; 037 import java.util.Collection; 038 import java.util.Date; 039 import java.util.Iterator; 040 import java.text.DateFormat; 041 import java.text.SimpleDateFormat; 042 043 import static org.kuali.ole.docstore.process.ProcessParameters.*; 044 045 /** 046 * Created by IntelliJ IDEA. 047 * User: pvsubrah 048 * Date: 9/11/11 049 * Time: 10:37 AM 050 * To change this template use File | Settings | File Templates. 051 */ 052 public class NodeHandler { 053 054 private static final Logger logger = LoggerFactory.getLogger(NodeHandler.class); 055 056 public Node initStaticNode(String nodeName, Node parentNode, Session session) throws RepositoryException { 057 Node node; 058 if (!parentNode.hasNode(nodeName)) { 059 synchronized (session) { 060 node = parentNode.addNode(nodeName, "nt:unstructured"); 061 node.setProperty("nodeType", "folder"); 062 node.addMixin("mix:referenceable"); 063 session.save(); 064 } 065 } 066 else { 067 node = parentNode.getNode(nodeName); 068 } 069 return node; 070 } 071 072 public Node initNonStaticNode(String nodeName, Node parentNode) throws RepositoryException { 073 Node node; 074 node = parentNode.addNode(nodeName, "nt:unstructured"); 075 node.setProperty("nodeType", "folder"); 076 node.addMixin("mix:referenceable"); 077 return node; 078 } 079 080 public synchronized Node initFileNode(RequestDocument document, String name, Node parentNode, Session session) 081 throws Exception { 082 DocStoreConstants docStoreConstants = new DocStoreConstants(); 083 String uuid = null; 084 Node fileNode = null; 085 try { 086 NodeIterator nodes = parentNode.getNodes(name); 087 if (nodes.getSize() >= BUCKET_SIZE_FILE_NODES) { 088 if (DocFormat.OLEML.isEqualTo(document.getFormat())) { 089 throw new RuntimeException("FileNode creation failed as the BUCKET_SIZE[" + BUCKET_SIZE_FILE_NODES 090 + "] is FULL: for the doc: " + document.getFormat() + "\n@ level: " 091 + parentNode.getPath() + "/" + name + "[" + (nodes.getSize() + 1) + "]"); 092 } 093 else { 094 parentNode = initLevelNode(parentNode.getName(), parentNode.getParent(), true, session); 095 } 096 } 097 098 fileNode = parentNode.addNode(name, "olefile"); 099 fileNode.addMixin("mix:referenceable"); 100 if (DocType.LICENSE.isEqualTo(document.getType()) || docStoreConstants.isVersioningEnabled ) { 101 fileNode.addMixin("mix:versionable"); 102 } 103 104 AdditionalAttributes additionalAttributes = document.getAdditionalAttributes(); 105 if (DocType.LICENSE.isEqualTo(document.getType()) && !DocFormat.ONIXPL.isEqualTo(document.getFormat())) { 106 String docName = new File(document.getDocumentName()).getName(); 107 additionalAttributes.setAttribute("dateLoaded", Calendar.getInstance().toString()); 108 additionalAttributes.setAttribute("fileName", docName); 109 additionalAttributes.setAttribute("owner", document.getUser()); 110 } 111 112 if (additionalAttributes != null) { 113 Collection<String> attributeNames = additionalAttributes.getAttributeNames(); 114 if (attributeNames != null && attributeNames.size() > 0) { 115 for (Iterator<String> iterator = attributeNames.iterator(); iterator.hasNext(); ) { 116 String attributeName = iterator.next(); 117 String attributeValue = additionalAttributes.getAttribute(attributeName); 118 fileNode.setProperty(attributeName, attributeValue); 119 } 120 } 121 122 } 123 else { 124 fileNode.setProperty("dateEntered", Calendar.getInstance()); 125 fileNode.setProperty("lastUpdated", Calendar.getInstance()); 126 } 127 128 Node resNode = fileNode.addNode("jcr:content", "nt:resource"); 129 resNode.setProperty("jcr:mimeType", "application/xml"); 130 resNode.setProperty("jcr:encoding", ""); 131 132 String charset = "UTF-8"; 133 byte[] documentBytes = null; 134 try { 135 uuid = fileNode.getIdentifier(); 136 document.setUuid(uuid); 137 // Content Manipulations 138 if (DocFormat.MARC.isEqualTo(document.getFormat())) { 139 new WorkBibMarcContentHandler().doPreIngestContentManipulations(document, uuid); 140 } 141 else if (DocFormat.OLEML.isEqualTo(document.getFormat())) { 142 (new WorkInstanceOleMLContentHandler()) 143 .doInstanceOleMLContentManipulations(document, uuid, parentNode); 144 } 145 146 if (document.getContent() != null && document.getContent().getContent() != null) { 147 documentBytes = document.getContent().getContent().getBytes(); 148 } 149 150 else if (document.getDocumentName() != null) { 151 File file = new File(document.getDocumentName()); 152 if (file.exists()) { 153 documentBytes = FileUtils.readFileToByteArray(file); 154 } 155 } 156 } 157 catch (Exception e) { 158 logger.error("Failed to convert document string to byte[] with charset " + charset, e); 159 } 160 InputStream docInputStream = new ByteArrayInputStream(documentBytes); 161 Binary binary = session.getValueFactory().createBinary(docInputStream); 162 resNode.setProperty("jcr:data", binary); 163 Calendar lastModified = Calendar.getInstance(); 164 lastModified.setTimeInMillis(new Date().getTime()); 165 resNode.setProperty("jcr:lastModified", lastModified); 166 logger.debug(fileNode.getPath() + " : " + uuid); 167 } 168 catch (RepositoryException e) { 169 logger.error("File Node Cannot be Created: " + e.getMessage(), e); 170 } 171 return fileNode; 172 } 173 174 /** 175 * Initializes the given fileNode with info from given requestDocument. 176 * 177 * @param fileNode 178 * @param document 179 * @param name 180 * @param parentNode 181 * @param session 182 * @return 183 * @throws Exception 184 */ 185 public synchronized Node initFileNode(Node fileNode, RequestDocument document, String name, Node parentNode, 186 Session session) throws Exception { 187 String uuid = null; 188 //Node fileNode = null; 189 DocStoreConstants docStoreConstants = new DocStoreConstants(); 190 try { 191 /*NodeIterator nodes = parentNode.getNodes(name); 192 if (nodes.getSize() >= BUCKET_SIZE_FILE_NODES) { 193 if (DocFormat.OLEML.isEqualTo(document.getFormat())) 194 throw new RuntimeException("FileNode creation failed as the BUCKET_SIZE[" + BUCKET_SIZE_FILE_NODES + "] is FULL: for the doc: " 195 + document.getFormat() + "\n@ level: " + parentNode.getPath() + "/" + name + "[" + (nodes.getSize() + 1) + "]"); 196 else 197 parentNode = initLevelNode(parentNode.getName(), parentNode.getParent(), true, session); 198 } 199 200 fileNode = parentNode.addNode(name, "olefile"); */ 201 DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss:SSS"); 202 Date date = new Date(); 203 //logger.info("NODE INIT: STARTING TIME \t" + dateFormat.format(date)); 204 fileNode.addMixin("mix:referenceable"); 205 if (DocType.LICENSE.isEqualTo(document.getType()) || docStoreConstants.isVersioningEnabled) { 206 fileNode.addMixin("mix:versionable"); 207 } 208 209 AdditionalAttributes additionalAttributes = document.getAdditionalAttributes(); 210 if (DocType.LICENSE.isEqualTo(document.getType()) && !DocFormat.ONIXPL.isEqualTo(document.getFormat())) { 211 String docName = new File(document.getDocumentName()).getName(); 212 additionalAttributes.setAttribute("dateLoaded", Calendar.getInstance().toString()); 213 additionalAttributes.setAttribute("fileName", docName); 214 additionalAttributes.setAttribute("owner", document.getUser()); 215 } 216 217 if (additionalAttributes != null) { 218 Collection<String> attributeNames = additionalAttributes.getAttributeNames(); 219 if (attributeNames != null && attributeNames.size() > 0) { 220 for (Iterator<String> iterator = attributeNames.iterator(); iterator.hasNext(); ) { 221 String attributeName = iterator.next(); 222 String attributeValue = additionalAttributes.getAttribute(attributeName); 223 fileNode.setProperty(attributeName, attributeValue); 224 } 225 } 226 227 } 228 else { 229 fileNode.setProperty("dateEntered", Calendar.getInstance()); 230 fileNode.setProperty("lastUpdated", Calendar.getInstance()); 231 } 232 233 Node resNode = fileNode.addNode("jcr:content", "nt:resource"); 234 resNode.setProperty("jcr:mimeType", "application/xml"); 235 resNode.setProperty("jcr:encoding", ""); 236 237 String charset = "UTF-8"; 238 byte[] documentBytes = null; 239 try { 240 uuid = fileNode.getIdentifier(); 241 document.setUuid(uuid); 242 // Content Manipulations 243 if (DocFormat.MARC.isEqualTo(document.getFormat())) { 244 new WorkBibMarcContentHandler().doPreIngestContentManipulations(document, uuid); 245 } 246 else if (DocFormat.OLEML.isEqualTo(document.getFormat())) { 247 (new WorkInstanceOleMLContentHandler()) 248 .doInstanceOleMLContentManipulations(document, uuid, parentNode); 249 } 250 251 if (document.getContent() != null && document.getContent().getContent() != null) { 252 documentBytes = document.getContent().getContent().getBytes(); 253 } 254 else if (document.getDocumentName() != null) { 255 File file = new File(document.getDocumentName()); 256 if (file.exists()) { 257 documentBytes = FileUtils.readFileToByteArray(file); 258 } 259 } 260 261 262 } 263 catch (Exception e) { 264 logger.error("Failed to convert document string to byte[] with charset " + charset, e); 265 } 266 InputStream docInputStream = new ByteArrayInputStream(documentBytes); 267 Binary binary = session.getValueFactory().createBinary(docInputStream); 268 resNode.setProperty("jcr:data", binary); 269 Calendar lastModified = Calendar.getInstance(); 270 lastModified.setTimeInMillis(new Date().getTime()); 271 resNode.setProperty("jcr:lastModified", lastModified); 272 logger.debug(fileNode.getPath() + " : " + uuid); 273 //logger.info("NODE INIT: ENDING TIME \t" + dateFormat.format(date)); 274 } 275 catch (RepositoryException e) { 276 logger.error("File Node Cannot be Created: " + e.getMessage(), e); 277 } 278 279 return fileNode; 280 } 281 282 public synchronized Node initLevelNode(String name, Node parent, boolean isRecursiveCall, Session session) 283 throws Exception { 284 long existing = 0; 285 try { 286 long bucketSize = BUCKET_SIZES.get(name); 287 boolean hasRepeatedChild = HAS_REPEATED_CHILD.get(name); 288 if (parent.hasNode(name)) { 289 NodeIterator existingNodes = parent.getNodes(name); 290 existing = existingNodes.getSize(); 291 if (existing <= bucketSize && !((isRecursiveCall && existing == bucketSize) || (!hasRepeatedChild 292 && existing 293 == bucketSize))) { 294 if (hasRepeatedChild && !isRecursiveCall) { 295 existingNodes.skip(existing - 1); 296 return existingNodes.nextNode(); 297 } 298 else { 299 Node levelNode = initNonStaticNode(name, parent); 300 if (existing == 0) { 301 session.save(); 302 } 303 return levelNode; 304 } 305 } 306 else { 307 if (!STATIC_NODES.contains(parent.getPath())) { 308 parent = initLevelNode(parent.getName(), parent.getParent(), true, session); 309 return initNonStaticNode(name, parent); 310 } 311 else { 312 throw new Exception("Node [" + parent.getName() + "/" + name + "[" + (existing + 1) 313 + "]] Cannot Be Created. CAUSE: TREE [" + bucketSize + "] FULL "); 314 } 315 } 316 } 317 else { 318 return initNonStaticNode(name, parent); 319 } 320 } 321 catch (Exception e) { 322 try { 323 logger.error( 324 "Exception While initializing Node: " + parent.getName() + "/" + name + "[" + (existing + 1) 325 + "] \t to Parent: " + parent.getName(), e); 326 } 327 catch (RepositoryException e1) { 328 } 329 throw e; 330 } 331 } 332 333 public Node getNodeByUUID(Session session, String uuid) throws OleException { 334 logger.debug("Started getting node for UUID:" + uuid); 335 boolean isNewSession = false; 336 if (null == session) { 337 isNewSession = true; 338 logger.debug("Initilalizing new session"); 339 session = RepositoryManager.getRepositoryManager().getSession("nodeHandler", "getNodeByUUID"); 340 } 341 try { 342 return session.getNodeByIdentifier(uuid); 343 } 344 catch (RepositoryException e) { 345 throw new OleException("getNodeByUUID failed", e); 346 } 347 finally { 348 if (isNewSession) { 349 RepositoryManager.getRepositoryManager().logout(session); 350 } 351 } 352 } 353 354 }