[
https://issues.apache.org/jira/browse/MINIFICPP-268?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16250593#comment-16250593
]
ASF GitHub Bot commented on MINIFICPP-268:
------------------------------------------
Github user phrocker commented on a diff in the pull request:
https://github.com/apache/nifi-minifi-cpp/pull/156#discussion_r148075762
--- Diff: extensions/libarchive/ManipulateArchive.cpp ---
@@ -0,0 +1,218 @@
+/**
+ * @file ManipulateArchive.cpp
+ * ManipulateArchive class implementation
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <memory>
+#include <string>
+#include <set>
+#include <list>
+#include <algorithm>
+
+#include <boost/filesystem.hpp>
+
+#include <archive.h>
+#include <archive_entry.h>
+
+#include "ManipulateArchive.h"
+#include "core/ProcessContext.h"
+#include "core/ProcessSession.h"
+#include "core/FlowFile.h"
+
+namespace org {
+namespace apache {
+namespace nifi {
+namespace minifi {
+namespace processors {
+
+core::Property ManipulateArchive::Operation("Operation", "Operation to
perform on the archive (touch, remove, copy, move).", "");
+core::Property ManipulateArchive::Target("Target", "An existing entry
within the archive to perform the operation on.", "");
+core::Property ManipulateArchive::Destination("Destination", "Destination
for operations (touch, move or copy) which result in new entries.", "");
+core::Property ManipulateArchive::Before("Before", "For operations which
result in new entries, places the new entry before the entry specified by this
property.", "");
+core::Property ManipulateArchive::After("After", "For operations which
result in new entries, places the new entry after the entry specified by this
property.", "");
+core::Relationship ManipulateArchive::Success("success", "FlowFiles will
be transferred to the success relationship if the operation succeeds.");
+core::Relationship ManipulateArchive::Failure("failure", "FlowFiles will
be transferred to the failure relationship if the operation fails.");
+
+char const* ManipulateArchive::OPERATION_REMOVE = "remove";
+char const* ManipulateArchive::OPERATION_COPY = "copy";
+char const* ManipulateArchive::OPERATION_MOVE = "move";
+char const* ManipulateArchive::OPERATION_TOUCH = "touch";
+
+void ManipulateArchive::initialize() {
+ //! Set the supported properties
+ std::set<core::Property> properties;
+ properties.insert(Operation);
+ properties.insert(Target);
+ properties.insert(Destination);
+ properties.insert(Before);
+ properties.insert(After);
+ setSupportedProperties(properties);
+
+ //! Set the supported relationships
+ std::set<core::Relationship> relationships;
+ relationships.insert(Success);
+ relationships.insert(Failure);
+ setSupportedRelationships(relationships);
+}
+
+void ManipulateArchive::onSchedule(core::ProcessContext *context,
core::ProcessSessionFactory *sessionFactory) {
+ context->getProperty(Operation.getName(), operation_);
+ std::transform(operation_.begin(), operation_.end(),
operation_.begin(), ::tolower);
+
+ bool op_create = operation_ == OPERATION_COPY ||
+ operation_ == OPERATION_MOVE ||
+ operation_ == OPERATION_TOUCH;
+
+ // Operation must be one of copy, move, touch or remove
+ assert(op_create || (operation_ == OPERATION_REMOVE));
+
+ context->getProperty(Target.getName(), targetEntry_);
+ context->getProperty(Destination.getName(), destination_);
+
+ // All operations which create new entries require a set destination
+ assert(op_create != destination_.empty());
+
+ // The only operation that doesn't require an existing target is touch
+ assert((operation_ == OPERATION_TOUCH) == targetEntry_.empty());
+
+ context->getProperty(Before.getName(), before_);
+ context->getProperty(After.getName(), after_);
+
+ // Users may specify one or none of before or after, but never both.
+ assert(!(before_.size() && after_.size()));
+}
+
+void ManipulateArchive::onTrigger(core::ProcessContext *context,
core::ProcessSession *session) {
+ std::shared_ptr<core::FlowFile> flowFile = session->get();
+
+ if (!flowFile) {
+ return;
+ }
+
+ FocusArchiveEntry::ArchiveMetadata archiveMetadata;
+ FocusArchiveEntry::ReadCallback readCallback(this, &archiveMetadata);
+ session->read(flowFile, &readCallback);
+
+ auto entries_end = archiveMetadata.entryMetadata.end();
+
+ auto target_position = scanArchiveEntries(archiveMetadata,
targetEntry_);
+
+ if (target_position == entries_end && operation_ != OPERATION_TOUCH) {
+ logger_->log_warn("ManipulateArchive could not find entry %s to
%s!",
+ targetEntry_.c_str(), operation_.c_str());
+ session->transfer(flowFile, Failure);
+ return;
+ } else {
+ logger_->log_info("ManipulateArchive found %s for %s.",
+ targetEntry_.c_str(), operation_.c_str());
+ }
+
+ if (!destination_.empty()) {
+ auto dest_position = scanArchiveEntries(archiveMetadata,
destination_);
+ if (dest_position != entries_end) {
+ logger_->log_warn("ManipulateArchive cannot perform %s to
existing destination_ %s!",
+ operation_.c_str(), destination_.c_str());
+ session->transfer(flowFile, Failure);
+ return;
+ }
+ }
+
+ std::list<FocusArchiveEntry::ArchiveEntryMetadata>::iterator position;
+
+ // Small speedup for when neither before or after are provided or
needed
+ if ((before_.empty() && after_.empty()) || operation_ ==
OPERATION_REMOVE) {
+ position = entries_end;
+ } else {
+ std::string positionEntry = after_.empty() ? before_ : after_;
+ position = scanArchiveEntries(archiveMetadata, positionEntry);
+
+ if (position == entries_end)
+ logger_->log_warn("ManipulateArchive could not find entry %s
to "
+ "perform %s %s; appending to end of
archive...",
--- End diff --
FYI You do not need to use c_str() when using the logger.
> Implement ManipulateArchive processor
> -------------------------------------
>
> Key: MINIFICPP-268
> URL: https://issues.apache.org/jira/browse/MINIFICPP-268
> Project: NiFi MiNiFi C++
> Issue Type: New Feature
> Reporter: Caleb Johnson
>
> The ManipulateArchive processor extends Un/FocusArchive by allowing users to
> perform the following operations on archives supported by same:
> * Touch: create an empty file at the specified path;
> * Remove: repacks an archive, but skips the specified entry when rebuilding;
> * Move: rename an archive entry;
> * Copy: duplicate an archive entry to another path.
> Touch, move and copy operations take optional 'before' and 'after' parameters
> to control where the modified entry is to be placed relative to an existing
> one.
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)