private static void decorateContentNode( final DocumentReader docReader, final DocumentWriter docWriter) { if (!docReader.getMixinTypeNames().contains(FEDORA_BINARY)) { LOGGER.trace("Adding mixin: {}, to {}", FEDORA_BINARY, docReader.getDocumentId()); docWriter.addMixinType(FEDORA_BINARY); } if (null == docReader.getProperty(CONTENT_DIGEST)) { final BinaryValue binaryValue = getBinaryValue(docReader); final String dsChecksum = binaryValue.getHexHash(); final String dsURI = asURI("SHA-1", dsChecksum).toString(); LOGGER.trace( "Adding {} property of {} to {}", CONTENT_DIGEST, dsURI, docReader.getDocumentId()); docWriter.addProperty(CONTENT_DIGEST, dsURI); } if (null == docReader.getProperty(CONTENT_SIZE)) { final BinaryValue binaryValue = getBinaryValue(docReader); final long binarySize = binaryValue.getSize(); LOGGER.trace( "Adding {} property of {} to {}", CONTENT_SIZE, binarySize, docReader.getDocumentId()); docWriter.addProperty(CONTENT_SIZE, binarySize); } LOGGER.debug("Decorated data property at path: {}", docReader.getDocumentId()); }
@Override public String getMimeType(BinaryValue binary, String name) throws IOException, RepositoryException { if (detector == null) { return null; } String detectedMimeType = detector.mimeTypeOf(name, binary); if (binary instanceof InMemoryBinaryValue) { return detectedMimeType; } Iterator<Map.Entry<String, BinaryStore>> it = getNamedStoreIterator(); while (it.hasNext()) { Map.Entry<String, BinaryStore> entry = it.next(); final String binaryStoreKey = entry.getKey(); BinaryStore bs = entry.getValue(); try { if (bs.hasBinary(binary.getKey())) { return bs.getMimeType(binary, name); } } catch (BinaryStoreException e) { logger.debug(e, "The named store " + binaryStoreKey + " raised exception"); if (!it.hasNext()) { throw e; } } } throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(binary.getKey(), this)); }
@Override public String getText(BinaryValue binary) throws BinaryStoreException { if (binary instanceof InMemoryBinaryValue) { if (extractors == null || !extractors.extractionEnabled()) { return null; } // The extracted text will never be stored, so try directly using the text extractors ... return extractors.extract((InMemoryBinaryValue) binary, new TextExtractorContext(detector)); } Iterator<Map.Entry<String, BinaryStore>> it = getNamedStoreIterator(); while (it.hasNext()) { Map.Entry<String, BinaryStore> entry = it.next(); final String binaryStoreKey = entry.getKey(); BinaryStore bs = entry.getValue(); try { if (bs.hasBinary(binary.getKey())) { return bs.getText(binary); } } catch (BinaryStoreException e) { logger.debug(e, "The named store " + binaryStoreKey + " raised exception"); if (!it.hasNext()) { throw e; } } } throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(binary.getKey(), this)); }
/** * Move a value from one named store to another store * * @param key Binary key to transfer from the source store to the destination store * @param source a hint for discovering the source repository; may be null * @param destination a hint for discovering the destination repository * @return the {@link BinaryKey} value of the moved binary, never {@code null} * @throws BinaryStoreException if a source store cannot be found or the source store does not * contain the binary key */ public BinaryKey moveValue(BinaryKey key, String source, String destination) throws BinaryStoreException { final BinaryStore sourceStore; if (source == null) { sourceStore = findBinaryStoreContainingKey(key); } else { sourceStore = selectBinaryStore(source); } // could not find source store, or if (sourceStore == null || !sourceStore.hasBinary(key)) { throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(key, sourceStore)); } BinaryStore destinationStore = selectBinaryStore(destination); // key is already in the destination store if (sourceStore.equals(destinationStore)) { return key; } final BinaryValue binaryValue = storeValue(sourceStore.getInputStream(key), destination); sourceStore.markAsUnused(java.util.Collections.singleton(key)); return binaryValue.getKey(); }
@Override public BinaryValue storeValue(InputStream stream, String hint) throws BinaryStoreException { BinaryStore binaryStore = selectBinaryStore(hint); BinaryValue bv = binaryStore.storeValue(stream); logger.debug("Stored binary " + bv.getKey() + " into binary store " + binaryStore); return bv; }
@Override protected String getStoredMimeType(BinaryValue source) throws BinaryStoreException { try { checkContentExists(source); ResultSet rs = session.execute( "SELECT mime_type FROM modeshape.binary WHERE cid = '" + source.getKey() + "';"); Row row = rs.one(); if (row == null) { throw new BinaryStoreException( JcrI18n.unableToFindBinaryValue.text(source.getKey(), session)); } return row.getString("mime_type"); } catch (BinaryStoreException e) { throw e; } catch (RuntimeException e) { throw new BinaryStoreException(e); } }
@Override protected void storeMimeType(BinaryValue source, String mimeType) throws BinaryStoreException { try { session.execute( "UPDATE modeshape.binary SET mime_type='" + mimeType + "' where cid='" + source.getKey() + "';"); } catch (RuntimeException e) { throw new BinaryStoreException(e); } }
@Override public void storeExtractedText(BinaryValue source, String extractedText) throws BinaryStoreException { try { session.execute( "UPDATE modeshape.binary SET ext_text='" + extractedText + "' where cid='" + source.getKey() + "';"); } catch (RuntimeException e) { throw new BinaryStoreException(e); } }
@Override public BinaryValue storeValue(InputStream stream) throws BinaryStoreException { // store into temporary file system store and get SHA-1 BinaryValue temp = cache.storeValue(stream); try { // prepare new binary key based on SHA-1 BinaryKey key = new BinaryKey(temp.getKey().toString()); // check for duplicate content if (this.contentExists(key, ALIVE)) { return new StoredBinaryValue(this, key, temp.getSize()); } // check unused content if (this.contentExists(key, UNUSED)) { session.execute("UPDATE modeshape.binary SET usage=1 WHERE cid='" + key + "';"); return new StoredBinaryValue(this, key, temp.getSize()); } // store content PreparedStatement query = session.prepare( "INSERT INTO modeshape.binary (cid, usage_time, payload, usage) VALUES ( ?,?,?,1 );"); BoundStatement statement = new BoundStatement(query); session.execute(statement.bind(key.toString(), new Date(), buffer(stream))); return new StoredBinaryValue(this, key, temp.getSize()); } catch (BinaryStoreException e) { throw e; } catch (IOException e) { throw new BinaryStoreException(e); } catch (RuntimeException e) { throw new BinaryStoreException(e); } finally { // remove content from temp store cache.markAsUnused(temp.getKey()); } }
private void checkContentExists(BinaryValue source) throws BinaryStoreException { if (!contentExists(source.getKey(), true)) { throw new BinaryStoreException( JcrI18n.unableToFindBinaryValue.text(source.getKey(), session)); } }
protected void addInformationForPath( Repository repository, Git git, DocumentWriter writer, RevCommit commit, String path, CallSpecification spec, Values values) throws GitAPIException, IOException { // Make sure the path is in the canonical form we need ... if (path.startsWith("/")) { if (path.length() == 1) path = ""; else path = path.substring(1); } // Now see if we're actually referring to the "jcr:content" node ... boolean isContentNode = false; if (path.endsWith(JCR_CONTENT_SUFFIX)) { isContentNode = true; path = path.substring(0, path.length() - JCR_CONTENT_SUFFIX.length()); } // Create the TreeWalk that we'll use to navigate the files/directories ... final TreeWalk tw = new TreeWalk(repository); tw.addTree(commit.getTree()); if ("".equals(path)) { // This is the top-level directory, so we don't need to pre-walk to find anything ... tw.setRecursive(false); while (tw.next()) { String childName = tw.getNameString(); String childId = spec.childId(childName); writer.addChild(childId, childName); } } else { // We need to first find our path *before* we can walk the children ... PathFilter filter = PathFilter.create(path); tw.setFilter(filter); while (tw.next()) { if (filter.isDone(tw)) { break; } else if (tw.isSubtree()) { tw.enterSubtree(); } } // Now that the TreeWalk is the in right location given by the 'path', we can get the if (tw.isSubtree()) { // The object at the 'path' is a directory, so go into it ... tw.enterSubtree(); // Find the commit in which this folder was last modified ... // This may not be terribly efficient, but it seems to work faster on subsequent runs ... RevCommit folderCommit = git.log().addPath(path).call().iterator().next(); // Add folder-related properties ... String committer = folderCommit.getCommitterIdent().getName(); String author = folderCommit.getAuthorIdent().getName(); DateTime committed = values.dateFrom(folderCommit.getCommitTime()); writer.setPrimaryType(GitLexicon.FOLDER); writer.addProperty(JcrLexicon.CREATED, committed); writer.addProperty(JcrLexicon.CREATED_BY, committer); writer.addProperty(GitLexicon.OBJECT_ID, folderCommit.getId().name()); writer.addProperty(GitLexicon.AUTHOR, author); writer.addProperty(GitLexicon.COMMITTER, committer); writer.addProperty(GitLexicon.COMMITTED, committed); writer.addProperty(GitLexicon.TITLE, folderCommit.getShortMessage()); // And now walk the contents of the directory ... while (tw.next()) { String childName = tw.getNameString(); String childId = spec.childId(childName); writer.addChild(childId, childName); } } else { // The path specifies a file (or a content node) ... // Find the commit in which this folder was last modified ... // This may not be terribly efficient, but it seems to work faster on subsequent runs ... RevCommit fileCommit = git.log().addPath(path).call().iterator().next(); // Add file-related properties ... String committer = fileCommit.getCommitterIdent().getName(); String author = fileCommit.getAuthorIdent().getName(); DateTime committed = values.dateFrom(fileCommit.getCommitTime()); if (isContentNode) { writer.setPrimaryType(GitLexicon.RESOURCE); writer.addProperty(JcrLexicon.LAST_MODIFIED, committed); writer.addProperty(JcrLexicon.LAST_MODIFIED_BY, committer); writer.addProperty(GitLexicon.OBJECT_ID, fileCommit.getId().name()); writer.addProperty(GitLexicon.AUTHOR, author); writer.addProperty(GitLexicon.COMMITTER, committer); writer.addProperty(GitLexicon.COMMITTED, committed); writer.addProperty(GitLexicon.TITLE, fileCommit.getShortMessage()); // Create the BinaryValue ... ObjectId fileObjectId = tw.getObjectId(0); ObjectLoader fileLoader = repository.open(fileObjectId); BinaryKey key = new BinaryKey(fileObjectId.getName()); BinaryValue value = values.binaryFor(key, fileLoader.getSize()); if (value == null) { // It wasn't found in the binary store ... if (fileLoader.isLarge()) { // Too large to hold in memory, so use the binary store (which reads the file // immediately) ... value = values.binaryFrom(fileLoader.openStream()); } else { // This is small enough to fit into a byte[], but it still may be pretty big ... value = new GitBinaryValue( fileObjectId, fileLoader, connector.getSourceName(), name, connector.getMimeTypeDetector()); } } writer.addProperty(JcrLexicon.DATA, value); if (connector.includeMimeType()) { try { String filename = spec.parameter(spec.parameterCount() - 1); // the last is 'jcr:content' String mimeType = value.getMimeType(filename); if (mimeType != null) writer.addProperty(JcrLexicon.MIMETYPE, mimeType); } catch (RepositoryException e) { // do nothing } catch (IOException e) { // do nothing } } } else { writer.setPrimaryType(GitLexicon.FILE); writer.addProperty(JcrLexicon.CREATED, committed); writer.addProperty(JcrLexicon.CREATED_BY, committer); writer.addProperty(GitLexicon.OBJECT_ID, fileCommit.getId().name()); writer.addProperty(GitLexicon.AUTHOR, author); writer.addProperty(GitLexicon.COMMITTER, committer); writer.addProperty(GitLexicon.COMMITTED, committed); writer.addProperty(GitLexicon.TITLE, fileCommit.getShortMessage()); // Add the "jcr:content" child node ... String childId = spec.childId(JCR_CONTENT); writer.addChild(childId, JCR_CONTENT); } } } }