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 */ 016package org.kuali.ole.repository; 017 018import org.apache.commons.io.FileUtils; 019import org.kuali.ole.RepositoryManager; 020import org.kuali.ole.docstore.DocStoreConstants; 021import org.kuali.ole.docstore.common.document.content.instance.Item; 022import org.kuali.ole.docstore.common.document.content.instance.OleHoldings; 023import org.kuali.ole.docstore.common.document.content.instance.SourceHoldings; 024import org.kuali.ole.docstore.common.document.content.instance.xstream.HoldingOlemlRecordProcessor; 025import org.kuali.ole.docstore.common.document.content.instance.xstream.ItemOlemlRecordProcessor; 026import org.kuali.ole.docstore.common.document.content.instance.xstream.SourceHoldingOlemlRecordProcessor; 027import org.kuali.ole.docstore.model.enums.DocType; 028import org.kuali.ole.docstore.model.xmlpojo.ingest.RequestDocument; 029import org.kuali.ole.docstore.process.ProcessParameters; 030import org.kuali.ole.docstore.service.DocumentIndexer; 031import org.kuali.ole.docstore.service.ServiceLocator; 032import org.kuali.ole.logger.DocStoreLogger; 033import org.kuali.ole.pojo.OleException; 034import org.slf4j.Logger; 035import org.slf4j.LoggerFactory; 036 037import javax.jcr.Binary; 038import javax.jcr.Node; 039import javax.jcr.RepositoryException; 040import javax.jcr.Session; 041import javax.jcr.version.VersionHistory; 042import javax.jcr.version.VersionIterator; 043import javax.jcr.version.VersionManager; 044import java.io.ByteArrayInputStream; 045import java.io.File; 046import java.util.Calendar; 047import java.util.Iterator; 048 049import static org.kuali.ole.docstore.process.ProcessParameters.FILE_ITEM; 050 051public class CheckinManager { 052 053 DocStoreLogger docStoreLogger = new DocStoreLogger(this.getClass().getName()); 054 private static final Logger LOG = LoggerFactory.getLogger(CheckinManager.class); 055 056 public String updateContent(RequestDocument requestDocument) throws OleException { 057 // List<String> ingestDocs = new ArrayList<String>(); 058 // List<String> uuids = new ArrayList<String>(); 059 // StringBuilder sb = new StringBuilder(); 060 // String uuid = null; 061 String content = null; 062 String latestVersion = null; 063 String checkInFail = "Check in failed. "; 064 content = requestDocument.getContent().getContent(); 065 if (requestDocument.getUuid() == null || requestDocument.getUuid().trim().length() == 0) { 066 requestDocument.setUuid(requestDocument.getId()); 067 } 068 // uuid = requestDocument.getUuid(); 069 // ingestDocs.add(sb.toString()); 070 // uuids.add(uuid); 071 if (DocType.INSTANCE.getCode().equalsIgnoreCase(requestDocument.getType()) && content == null 072 && requestDocument.getId() != null) { 073 for (RequestDocument linkedItemDocument : requestDocument.getLinkedRequestDocuments()) { 074 if (DocType.ITEM.getDescription().equalsIgnoreCase(linkedItemDocument.getType()) 075 && linkedItemDocument.getContent().getContent() != null) { 076 ingestNIndexItemRecForInstance(requestDocument); 077 } 078 } 079 } 080 if (!DocType.SOURCEHOLDINGS.getDescription().equalsIgnoreCase(requestDocument.getType())) { 081 String result = ServiceLocator.getIndexerService().indexDocument(requestDocument); 082 if (!result.startsWith("success")) { 083 throw new OleException(checkInFail + result); 084 } 085 } 086 Session session = null; 087 try { 088 latestVersion = updateRecordInDocStore(requestDocument); 089 } catch (Exception e) { 090 docStoreLogger 091 .log("Document was updated in indexer but not in docStore, trying to rollback the changes from indexer", 092 e); 093 094 RequestDocument prevRequestDoc = null; 095 session = RepositoryManager.getRepositoryManager().getSession("CheckinManager", "checkIn"); 096 Node nodeByUUID = getNodeByUUID(session, requestDocument.getId()); 097 try { 098 DocumentIndexer documentIndexer = new DocumentIndexer(); 099 prevRequestDoc = new RequestDocument(); 100 prevRequestDoc = requestDocument; 101 String prevContent = nodeByUUID.getNode("jcr:content").getProperty("jcr:data").getValue().getString(); 102 prevRequestDoc.getContent().setContent(prevContent); 103 documentIndexer.indexDocument(prevRequestDoc); 104 } catch (Exception ex) { 105 String failMsg = checkInFail + "Unable to Roll back the changes in indexer. Record UUID " 106 + requestDocument.getId() + "got updated in indexer, but not in docstore "; 107 docStoreLogger.log(failMsg, ex); 108 throw new OleException(failMsg, ex); 109 110 } 111 docStoreLogger.log(checkInFail, e); 112 throw new OleException(checkInFail, e); 113 } finally { 114 RepositoryManager.getRepositoryManager().logout(session); 115 } 116 117 118 return latestVersion; 119 } 120 121 private void ingestNIndexItemRecForInstance(RequestDocument reqDoc) throws OleException { 122 Session session = null; 123 try { 124 session = RepositoryManager.getRepositoryManager() 125 .getSession("CheckinManager", "ingestNIndexItemRecForInstance"); 126 Node nodeByUUID = getNodeByUUID(session, reqDoc.getId()); 127 Node holdingsNode = nodeByUUID.getNode(ProcessParameters.NODE_HOLDINGS); 128 NodeHandler nodeHandler = new NodeHandler(); 129 130 for (RequestDocument linkedItemDocument : reqDoc.getLinkedRequestDocuments()) { 131 ItemOlemlRecordProcessor recordProcessor = new ItemOlemlRecordProcessor(); 132 Item item = recordProcessor.fromXML(linkedItemDocument.getContent().getContent()); 133 linkedItemDocument.getContent().setContentObject(item); 134 String uuid = (nodeHandler.initFileNode(linkedItemDocument, FILE_ITEM, holdingsNode, session)) 135 .getIdentifier(); 136 linkedItemDocument.setId(uuid); 137 } 138 session.save(); 139 } catch (Exception e) { 140 docStoreLogger.log(e.getMessage()); 141 throw new OleException(e.getMessage(), e); 142 } finally { 143 RepositoryManager.getRepositoryManager().logout(session); 144 } 145 } 146 147 148 private String updateRecordInDocStore(RequestDocument reqDoc) throws OleException, RepositoryException { 149 Session session = RepositoryManager.getRepositoryManager() 150 .getSession("CheckinManager", "updateRecordInDocStore"); 151 String charset = "UTF-8"; 152 byte[] documentBytes = null; 153 String currentVersion = null; 154 155 try { 156 if (reqDoc.getDocumentName() != null && reqDoc.getDocumentName().trim().length() != 0) { 157 documentBytes = FileUtils.readFileToByteArray(new File(reqDoc.getDocumentName())); 158 } else if (reqDoc.getContent().getContent() != null) { 159 setIdentifierValueInContent(reqDoc); 160 documentBytes = reqDoc.getContent().getContent().getBytes(charset); 161 } 162 } catch (Exception e) { 163 getDocStoreLogger().log("Failed to convert input string to byte[] with charset " + charset, e); 164 throw new OleException(e.getMessage()); 165 } 166 RequestDocument linkReqInfo = new RequestDocument(); 167 if (reqDoc.getLinkedRequestDocuments() != null && reqDoc.getLinkedRequestDocuments().size() > 0) { 168 for (Iterator<RequestDocument> linkIterator = reqDoc.getLinkedRequestDocuments().iterator(); linkIterator 169 .hasNext(); ) { 170 linkReqInfo = linkIterator.next(); 171 } 172 } 173 Node nodeByUUID = session.getNodeByIdentifier(reqDoc.getUuid()); 174 try { 175 Binary binary = null; 176 if (documentBytes != null) { 177 binary = session.getValueFactory().createBinary(new ByteArrayInputStream(documentBytes)); 178 nodeByUUID.getNode("jcr:content").setProperty("jcr:data", binary); 179 } 180 if (linkReqInfo != null && linkReqInfo.getId() != null && linkReqInfo.getType().equalsIgnoreCase( 181 DocType.INSTANCE.getCode())) { 182 nodeByUUID.setProperty("instanceIdentifier", linkReqInfo.getId()); 183 } 184 Calendar lastModified = Calendar.getInstance(); 185 lastModified.setTimeInMillis(lastModified.getTimeInMillis()); 186 if (!reqDoc.getType().equalsIgnoreCase(DocType.INSTANCE.getCode())) { 187 nodeByUUID.getNode("jcr:content").setProperty("jcr:lastModified", lastModified); 188 } 189 session.save(); 190 if (DocStoreConstants.isVersioningEnabled || DocType.LICENSE.isEqualTo(reqDoc.getType())) { 191 VersionManager versionManager = getVersionManager(session); 192 versionManager.checkpoint(nodeByUUID.getPath()); 193 VersionHistory versionHistory = versionManager.getVersionHistory(nodeByUUID.getPath()); 194 VersionIterator allVersions = versionHistory.getAllVersions(); 195 while (allVersions.hasNext()) { 196 currentVersion = allVersions.nextVersion().getName(); 197 } 198 getDocStoreLogger() 199 .log("Version updated for UUID:" + reqDoc.getUuid() + " ==== version:" + currentVersion); 200 } 201 } catch (Exception e) { 202 docStoreLogger.log(e.getMessage()); 203 throw new OleException(e.getMessage(), e); 204 } finally { 205 RepositoryManager.getRepositoryManager().logout(session); 206 } 207 return currentVersion; 208 } 209 210 private void setIdentifierValueInContent(RequestDocument reqDoc) { 211 if (reqDoc.getType().equalsIgnoreCase(DocType.ITEM.getDescription())) { 212 ItemOlemlRecordProcessor recordProcessor = new ItemOlemlRecordProcessor(); 213 Item item = recordProcessor.fromXML(reqDoc.getContent().getContent()); 214 item.setItemIdentifier(reqDoc.getId()); 215 reqDoc.getContent().setContent(recordProcessor.toXML(item)); 216 } 217 if (reqDoc.getType().equalsIgnoreCase(DocType.HOLDINGS.getDescription())) { 218 HoldingOlemlRecordProcessor recordProcessor = new HoldingOlemlRecordProcessor(); 219 OleHoldings holdings = recordProcessor.fromXML(reqDoc.getContent().getContent()); 220 holdings.setHoldingsIdentifier(reqDoc.getId()); 221 reqDoc.getContent().setContent(recordProcessor.toXML(holdings)); 222 } 223 if (reqDoc.getType().equalsIgnoreCase(DocType.SOURCEHOLDINGS.getDescription())) { 224 SourceHoldingOlemlRecordProcessor recordProcessor = new SourceHoldingOlemlRecordProcessor(); 225 SourceHoldings sourceHoldings = recordProcessor.fromXML(reqDoc.getContent().getContent()); 226 sourceHoldings.setHoldingsIdentifier(reqDoc.getId()); 227 reqDoc.getContent().setContent(recordProcessor.toXML(sourceHoldings)); 228 } 229 } 230 231 private Node getNodeByUUID(Session newSession, String uuid) throws OleException { 232 return new NodeHandler().getNodeByUUID(newSession, uuid); 233 } 234 235 public DocStoreLogger getDocStoreLogger() { 236 return docStoreLogger; 237 } 238 239 public VersionManager getVersionManager(Session session) throws OleException, RepositoryException { 240 return session.getWorkspace().getVersionManager(); 241 } 242}