http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/pom.xml b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/pom.xml new file mode 100644 index 0000000..fdbb58b --- /dev/null +++ b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/pom.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>${groupId}</groupId> + <artifactId>${rootArtifactId}</artifactId> + <version>${version}</version> + </parent> + + <artifactId>nifi-${artifactBaseName}</artifactId> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>${groupId}</groupId> + <artifactId>nifi-${artifactBaseName}-api</artifactId> + <version>${version}</version> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-api</artifactId> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-processor-utils</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-mock</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>test</scope> + </dependency> + </dependencies> +</project>
http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/java/StandardMyService.java ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/java/StandardMyService.java b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/java/StandardMyService.java new file mode 100644 index 0000000..193e6b7 --- /dev/null +++ b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/java/StandardMyService.java @@ -0,0 +1,80 @@ +/* + * 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. + */ +package ${package}; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.nifi.annotation.documentation.CapabilityDescription; +import org.apache.nifi.annotation.documentation.Tags; +import org.apache.nifi.annotation.lifecycle.OnDisabled; +import org.apache.nifi.annotation.lifecycle.OnEnabled; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.controller.AbstractControllerService; +import org.apache.nifi.controller.ConfigurationContext; +import org.apache.nifi.processor.exception.ProcessException; +import org.apache.nifi.processor.util.StandardValidators; +import org.apache.nifi.reporting.InitializationException; + +@Tags({ "example"}) +@CapabilityDescription("Example ControllerService implementation of MyService.") +public class StandardMyService extends AbstractControllerService implements MyService { + + public static final PropertyDescriptor MY_PROPERTY = new PropertyDescriptor + .Builder().name("My Property") + .description("Example Property") + .required(true) + .addValidator(StandardValidators.NON_EMPTY_VALIDATOR) + .build(); + + private static final List<PropertyDescriptor> properties; + + static { + final List<PropertyDescriptor> props = new ArrayList<>(); + props.add(MY_PROPERTY); + properties = Collections.unmodifiableList(props); + } + + @Override + protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { + return properties; + } + + /** + * @param context + * the configuration context + * @throws InitializationException + * if unable to create a database connection + */ + @OnEnabled + public void onEnabled(final ConfigurationContext context) throws InitializationException { + + } + + @OnDisabled + public void shutdown() { + + } + + @Override + public void execute() throws ProcessException { + + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService new file mode 100644 index 0000000..811fcd3 --- /dev/null +++ b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService @@ -0,0 +1,15 @@ +# 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. +${package}.StandardMyService \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestProcessor.java ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestProcessor.java b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestProcessor.java new file mode 100644 index 0000000..be00a70 --- /dev/null +++ b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestProcessor.java @@ -0,0 +1,45 @@ +/* + * 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. + */ +package ${package}; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.processor.AbstractProcessor; +import org.apache.nifi.processor.ProcessContext; +import org.apache.nifi.processor.ProcessSession; +import org.apache.nifi.processor.exception.ProcessException; + +public class TestProcessor extends AbstractProcessor { + + @Override + public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException { + } + + @Override + protected List<PropertyDescriptor> getSupportedPropertyDescriptors() { + List<PropertyDescriptor> propDescs = new ArrayList<>(); + propDescs.add(new PropertyDescriptor.Builder() + .name("MyService test processor") + .description("MyService test processor") + .identifiesControllerService(MyService.class) + .required(true) + .build()); + return propDescs; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestStandardMyService.java ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestStandardMyService.java b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestStandardMyService.java new file mode 100644 index 0000000..3f430e6 --- /dev/null +++ b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/nifi-__artifactBaseName__/src/test/java/TestStandardMyService.java @@ -0,0 +1,45 @@ +/* + * 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. + */ +package ${package}; + +import org.apache.nifi.reporting.InitializationException; +import org.apache.nifi.util.TestRunner; +import org.apache.nifi.util.TestRunners; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class TestStandardMyService { + + @Before + public void init() { + + } + + @Test + public void testService() throws InitializationException { + final TestRunner runner = TestRunners.newTestRunner(TestProcessor.class); + final StandardMyService service = new StandardMyService(); + runner.addControllerService("test-good", service); + + runner.setProperty(service, StandardMyService.MY_PROPERTY, "test-value"); + runner.enableControllerService(service); + + runner.assertValid(service); + } + +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/pom.xml b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/pom.xml new file mode 100644 index 0000000..0f32431 --- /dev/null +++ b/nifi-maven-archetypes/nifi-service-bundle-archetype/src/main/resources/archetype-resources/pom.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-nar-bundles</artifactId> + <version>${nifiVersion}</version> + </parent> + + <groupId>${groupId}</groupId> + <artifactId>${artifactId}</artifactId> + <version>${version}</version> + <packaging>pom</packaging> + + <modules> + <module>nifi-${artifactBaseName}-api</module> + <module>nifi-${artifactBaseName}-api-nar</module> + <module>nifi-${artifactBaseName}</module> + <module>nifi-${artifactBaseName}-nar</module> + </modules> + +</project> http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-maven-archetypes/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-maven-archetypes/pom.xml b/nifi-maven-archetypes/pom.xml new file mode 100644 index 0000000..b817604 --- /dev/null +++ b/nifi-maven-archetypes/pom.xml @@ -0,0 +1,30 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi</artifactId> + <version>0.3.0-SNAPSHOT</version> + </parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-maven-archetypes</artifactId> + <packaging>pom</packaging> + <modules> + <module>nifi-processor-bundle-archetype</module> + <module>nifi-service-bundle-archetype</module> + </modules> +</project> http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-mock/pom.xml b/nifi-mock/pom.xml new file mode 100644 index 0000000..8db3830 --- /dev/null +++ b/nifi-mock/pom.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi</artifactId> + <version>0.3.0-SNAPSHOT</version> + </parent> + <artifactId>nifi-mock</artifactId> + <dependencies> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-utils</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-expression-language</artifactId> + </dependency> + <dependency> + <groupId>org.apache.nifi</groupId> + <artifactId>nifi-data-provenance-utils</artifactId> + </dependency> + <dependency> + <!-- Dependency marked as provided, not test, because we have assertion + methods in our MockSession & MockFlowFile --> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/provenance/MockProvenanceEventRepository.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/provenance/MockProvenanceEventRepository.java b/nifi-mock/src/main/java/org/apache/nifi/provenance/MockProvenanceEventRepository.java new file mode 100644 index 0000000..241041a --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/provenance/MockProvenanceEventRepository.java @@ -0,0 +1,131 @@ +/* + * 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. + */ +package org.apache.nifi.provenance; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; + +import org.apache.nifi.events.EventReporter; +import org.apache.nifi.provenance.lineage.ComputeLineageSubmission; +import org.apache.nifi.provenance.search.Query; +import org.apache.nifi.provenance.search.QuerySubmission; +import org.apache.nifi.provenance.search.SearchableField; + +public class MockProvenanceEventRepository implements ProvenanceEventRepository { + + private final List<ProvenanceEventRecord> records = new ArrayList<>(); + private final AtomicLong idGenerator = new AtomicLong(0L); + + @Override + public void registerEvents(final Iterable<ProvenanceEventRecord> events) { + for (final ProvenanceEventRecord event : events) { + registerEvent(event); + } + } + + @Override + public void registerEvent(final ProvenanceEventRecord event) { + final StandardProvenanceEventRecord newRecord; + if (event instanceof StandardProvenanceEventRecord) { + newRecord = (StandardProvenanceEventRecord) event; + } else { + newRecord = new StandardProvenanceEventRecord.Builder().fromEvent(event).build(); + } + newRecord.setEventId(idGenerator.getAndIncrement()); + + records.add(newRecord); + } + + @Override + public void initialize(EventReporter reporter) throws IOException { + } + + @Override + public List<ProvenanceEventRecord> getEvents(long firstRecordId, int maxRecords) throws IOException { + if (firstRecordId > records.size()) { + return Collections.emptyList(); + } + + return records.subList((int) firstRecordId, Math.min(records.size(), (int) (firstRecordId + maxRecords))); + } + + @Override + public Long getMaxEventId() { + return Long.valueOf(records.size() - 1); + } + + @Override + public QuerySubmission submitQuery(Query query) { + throw new UnsupportedOperationException("MockProvenanceEventRepository does not support querying"); + } + + @Override + public QuerySubmission retrieveQuerySubmission(String queryIdentifier) { + throw new UnsupportedOperationException("MockProvenanceEventRepository does not support querying"); + } + + @Override + public ComputeLineageSubmission submitLineageComputation(String flowFileUuid) { + throw new UnsupportedOperationException("MockProvenanceEventRepository does not support Lineage Computation"); + } + + @Override + public ComputeLineageSubmission retrieveLineageSubmission(String lineageIdentifier) { + throw new UnsupportedOperationException("MockProvenanceEventRepository does not support Lineage Computation"); + } + + @Override + public ProvenanceEventRecord getEvent(long id) throws IOException { + if (id > records.size()) { + return null; + } + + return records.get((int) id); + } + + @Override + public ComputeLineageSubmission submitExpandParents(long eventId) { + throw new UnsupportedOperationException("MockProvenanceEventRepository does not support Lineage Computation"); + } + + @Override + public ComputeLineageSubmission submitExpandChildren(long eventId) { + throw new UnsupportedOperationException("MockProvenanceEventRepository does not support Lineage Computation"); + } + + @Override + public void close() throws IOException { + } + + @Override + public List<SearchableField> getSearchableFields() { + return Collections.emptyList(); + } + + @Override + public List<SearchableField> getSearchableAttributes() { + return Collections.emptyList(); + } + + @Override + public ProvenanceEventBuilder eventBuilder() { + return new StandardProvenanceEventRecord.Builder(); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/reporting/BulletinFactory.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/reporting/BulletinFactory.java b/nifi-mock/src/main/java/org/apache/nifi/reporting/BulletinFactory.java new file mode 100644 index 0000000..221bed6 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/reporting/BulletinFactory.java @@ -0,0 +1,43 @@ +/* + * 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. + */ +package org.apache.nifi.reporting; + +import java.util.concurrent.atomic.AtomicLong; + +public class BulletinFactory { + + private static final AtomicLong currentId = new AtomicLong(0); + + public static Bulletin createBulletin(final String groupId, final String sourceId, final String sourceName, final String category, final String severity, final String message) { + final Bulletin bulletin = new MockBulletin(currentId.getAndIncrement()); + bulletin.setGroupId(groupId); + bulletin.setSourceId(sourceId); + bulletin.setSourceName(sourceName); + bulletin.setCategory(category); + bulletin.setLevel(severity); + bulletin.setMessage(message); + return bulletin; + } + + public static Bulletin createBulletin(final String category, final String severity, final String message) { + final Bulletin bulletin = new MockBulletin(currentId.getAndIncrement()); + bulletin.setCategory(category); + bulletin.setLevel(severity); + bulletin.setMessage(message); + return bulletin; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/reporting/MockBulletin.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/reporting/MockBulletin.java b/nifi-mock/src/main/java/org/apache/nifi/reporting/MockBulletin.java new file mode 100644 index 0000000..652fd51 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/reporting/MockBulletin.java @@ -0,0 +1,24 @@ +/* + * 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. + */ +package org.apache.nifi.reporting; + +public class MockBulletin extends Bulletin { + + protected MockBulletin(long id) { + super(id); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/ControllerServiceConfiguration.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/ControllerServiceConfiguration.java b/nifi-mock/src/main/java/org/apache/nifi/util/ControllerServiceConfiguration.java new file mode 100644 index 0000000..bd623ca --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/ControllerServiceConfiguration.java @@ -0,0 +1,74 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.controller.ControllerService; + +public class ControllerServiceConfiguration { + + private final ControllerService service; + private final AtomicBoolean enabled = new AtomicBoolean(false); + private String annotationData; + private Map<PropertyDescriptor, String> properties = new HashMap<>(); + + public ControllerServiceConfiguration(final ControllerService service) { + this.service = service; + } + + public ControllerService getService() { + return service; + } + + public void setEnabled(final boolean enabled) { + this.enabled.set(enabled); + } + + public boolean isEnabled() { + return this.enabled.get(); + } + + public void setProperties(final Map<PropertyDescriptor, String> props) { + this.properties = new HashMap<>(props); + } + + public String getProperty(final PropertyDescriptor descriptor) { + final String value = properties.get(descriptor); + if (value == null) { + return descriptor.getDefaultValue(); + } else { + return value; + } + } + + public void setAnnotationData(final String annotationData) { + this.annotationData = annotationData; + } + + public String getAnnotationData() { + return annotationData; + } + + public Map<PropertyDescriptor, String> getProperties() { + return Collections.unmodifiableMap(properties); + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockBulletinRepository.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockBulletinRepository.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockBulletinRepository.java new file mode 100644 index 0000000..04fc496 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockBulletinRepository.java @@ -0,0 +1,74 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.util.List; + +import org.apache.nifi.reporting.Bulletin; +import org.apache.nifi.reporting.BulletinQuery; +import org.apache.nifi.reporting.BulletinRepository; + +public class MockBulletinRepository implements BulletinRepository { + + @Override + public void addBulletin(Bulletin bulletin) { + // TODO: Implement + + } + + @Override + public int getControllerBulletinCapacity() { + // TODO: Implement + return 0; + } + + @Override + public int getComponentBulletinCapacity() { + // TODO: Implement + return 0; + } + + @Override + public List<Bulletin> findBulletins(BulletinQuery bulletinQuery) { + // TODO: Implement + return null; + } + + @Override + public List<Bulletin> findBulletinsForGroupBySource(String groupId) { + // TODO: Implement + return null; + } + + @Override + public List<Bulletin> findBulletinsForGroupBySource(String groupId, int maxPerComponent) { + // TODO: Implement + return null; + } + + @Override + public List<Bulletin> findBulletinsForController() { + // TODO: Implement + return null; + } + + @Override + public List<Bulletin> findBulletinsForController(int max) { + // TODO: Implement + return null; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockConfigurationContext.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockConfigurationContext.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockConfigurationContext.java new file mode 100644 index 0000000..c90e722 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockConfigurationContext.java @@ -0,0 +1,77 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.controller.ConfigurationContext; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceLookup; + +public class MockConfigurationContext implements ConfigurationContext { + + private final Map<PropertyDescriptor, String> properties; + private final ControllerServiceLookup serviceLookup; + private final ControllerService service; + + public MockConfigurationContext(final Map<PropertyDescriptor, String> properties, final ControllerServiceLookup serviceLookup) { + this(null, properties, serviceLookup); + } + + public MockConfigurationContext(final ControllerService service, final Map<PropertyDescriptor, String> properties, final ControllerServiceLookup serviceLookup) { + this.service = service; + this.properties = properties; + this.serviceLookup = serviceLookup; + } + + @Override + public PropertyValue getProperty(final PropertyDescriptor property) { + String value = properties.get(property); + if (value == null) { + value = getActualDescriptor(property).getDefaultValue(); + } + return new MockPropertyValue(value, serviceLookup); + } + + @Override + public Map<PropertyDescriptor, String> getProperties() { + return new HashMap<>(this.properties); + } + + private PropertyDescriptor getActualDescriptor(final PropertyDescriptor property) { + if (service == null) { + return property; + } + + final PropertyDescriptor resolved = service.getPropertyDescriptor(property.getName()); + return resolved == null ? property : resolved; + } + + @Override + public String getSchedulingPeriod() { + return "0 secs"; + } + + @Override + public Long getSchedulingPeriod(final TimeUnit timeUnit) { + return 0L; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceInitializationContext.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceInitializationContext.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceInitializationContext.java new file mode 100644 index 0000000..bff1d62 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceInitializationContext.java @@ -0,0 +1,58 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceInitializationContext; +import org.apache.nifi.controller.ControllerServiceLookup; +import org.apache.nifi.logging.ComponentLog; + +public class MockControllerServiceInitializationContext extends MockControllerServiceLookup implements ControllerServiceInitializationContext, ControllerServiceLookup { + + private final String identifier; + private final ComponentLog logger; + + public MockControllerServiceInitializationContext(final ControllerService controllerService, final String identifier) { + this(controllerService, identifier, new MockProcessorLog(identifier, controllerService)); + } + + public MockControllerServiceInitializationContext(final ControllerService controllerService, final String identifier, final ComponentLog logger) { + this.identifier = identifier; + this.logger = logger; + addControllerService(controllerService, identifier); + } + + @Override + public String getIdentifier() { + return identifier; + } + + @Override + public String getControllerServiceName(final String serviceIdentifier) { + return null; + } + + @Override + public ControllerServiceLookup getControllerServiceLookup() { + return this; + } + + @Override + public ComponentLog getLogger() { + return logger; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceLookup.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceLookup.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceLookup.java new file mode 100644 index 0000000..219ee24 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockControllerServiceLookup.java @@ -0,0 +1,100 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceLookup; + +public abstract class MockControllerServiceLookup implements ControllerServiceLookup { + + private final Map<String, ControllerServiceConfiguration> controllerServiceMap = new ConcurrentHashMap<>(); + + public ControllerServiceConfiguration addControllerService(final ControllerService service, final String identifier) { + final ControllerServiceConfiguration config = new ControllerServiceConfiguration(service); + controllerServiceMap.put(identifier, config); + return config; + } + + public ControllerServiceConfiguration addControllerService(final ControllerService service) { + return addControllerService(service, service.getIdentifier()); + } + + public void removeControllerService(ControllerService service) { + final ControllerService canonical = getControllerService(service.getIdentifier()); + if (canonical == null || canonical != service) { + throw new IllegalArgumentException("Controller Service " + service + " is not known"); + } + + controllerServiceMap.remove(service.getIdentifier()); + } + + protected void addControllerServices(final MockControllerServiceLookup other) { + this.controllerServiceMap.putAll(other.controllerServiceMap); + } + + protected ControllerServiceConfiguration getConfiguration(final String identifier) { + return controllerServiceMap.get(identifier); + } + + @Override + public ControllerService getControllerService(final String identifier) { + final ControllerServiceConfiguration status = controllerServiceMap.get(identifier); + return (status == null) ? null : status.getService(); + } + + @Override + public boolean isControllerServiceEnabled(final String serviceIdentifier) { + final ControllerServiceConfiguration status = controllerServiceMap.get(serviceIdentifier); + if (status == null) { + throw new IllegalArgumentException("No ControllerService exists with identifier " + serviceIdentifier); + } + + return status.isEnabled(); + } + + @Override + public boolean isControllerServiceEnabled(final ControllerService service) { + return isControllerServiceEnabled(service.getIdentifier()); + } + + @Override + public boolean isControllerServiceEnabling(final String serviceIdentifier) { + return false; + } + + @Override + public Set<String> getControllerServiceIdentifiers(final Class<? extends ControllerService> serviceType) { + final Set<String> ids = new HashSet<>(); + for (final Map.Entry<String, ControllerServiceConfiguration> entry : controllerServiceMap.entrySet()) { + if (serviceType.isAssignableFrom(entry.getValue().getService().getClass())) { + ids.add(entry.getKey()); + } + } + return ids; + } + + @Override + public String getControllerServiceName(String serviceIdentifier) { + final ControllerServiceConfiguration status = controllerServiceMap.get(serviceIdentifier); + return status == null ? null : serviceIdentifier; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockEventAccess.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockEventAccess.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockEventAccess.java new file mode 100644 index 0000000..b5f6b11 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockEventAccess.java @@ -0,0 +1,70 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.nifi.controller.status.ProcessGroupStatus; +import org.apache.nifi.provenance.ProvenanceEventRecord; +import org.apache.nifi.provenance.ProvenanceEventRepository; +import org.apache.nifi.reporting.EventAccess; + +public class MockEventAccess implements EventAccess { + + private ProcessGroupStatus processGroupStatus; + private final List<ProvenanceEventRecord> provenanceRecords = new ArrayList<>(); + + public void setProcessGroupStatus(final ProcessGroupStatus status) { + this.processGroupStatus = status; + } + + @Override + public ProcessGroupStatus getControllerStatus() { + return processGroupStatus; + } + + @Override + public List<ProvenanceEventRecord> getProvenanceEvents(long firstEventId, int maxRecords) throws IOException { + if (firstEventId < 0 || maxRecords < 1) { + throw new IllegalArgumentException(); + } + + final List<ProvenanceEventRecord> records = new ArrayList<>(); + + for (final ProvenanceEventRecord record : provenanceRecords) { + if (record.getEventId() >= firstEventId) { + records.add(record); + if (records.size() >= maxRecords) { + return records; + } + } + } + + return records; + } + + public void addProvenanceEvent(final ProvenanceEventRecord record) { + this.provenanceRecords.add(record); + } + + @Override + public ProvenanceEventRepository getProvenanceRepository() { + return null; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFile.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFile.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFile.java new file mode 100644 index 0000000..e9fb9d6 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFile.java @@ -0,0 +1,277 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.nifi.flowfile.FlowFile; +import org.apache.nifi.flowfile.attributes.CoreAttributes; + +import org.junit.Assert; + +public class MockFlowFile implements FlowFile { + + private final Map<String, String> attributes = new HashMap<>(); + + private final long id; + private final long entryDate; + private final Set<String> lineageIdentifiers = new HashSet<>(); + private final long creationTime; + private boolean penalized = false; + + private byte[] data = new byte[0]; + + public MockFlowFile(final long id) { + this.creationTime = System.nanoTime(); + this.id = id; + entryDate = System.currentTimeMillis(); + attributes.put(CoreAttributes.FILENAME.key(), String.valueOf(System.nanoTime()) + ".mockFlowFile"); + attributes.put(CoreAttributes.PATH.key(), "target"); + + final String uuid = UUID.randomUUID().toString(); + attributes.put(CoreAttributes.UUID.key(), uuid); + lineageIdentifiers.add(uuid); + } + + public MockFlowFile(final long id, final FlowFile toCopy) { + this(id); + attributes.putAll(toCopy.getAttributes()); + final byte[] dataToCopy = ((MockFlowFile) toCopy).data; + this.data = new byte[dataToCopy.length]; + System.arraycopy(dataToCopy, 0, this.data, 0, dataToCopy.length); + + lineageIdentifiers.addAll(toCopy.getLineageIdentifiers()); + } + + void setPenalized() { + this.penalized = true; + } + + public long getCreationTime() { + return creationTime; + } + + @Override + public Set<String> getLineageIdentifiers() { + return lineageIdentifiers; + } + + @Override + public long getLineageStartDate() { + return entryDate; + } + + @Override + public int compareTo(final FlowFile o) { + return getAttribute(CoreAttributes.UUID.key()).compareTo(o.getAttribute(CoreAttributes.UUID.key())); + } + + @Override + public String getAttribute(final String attrName) { + return attributes.get(attrName); + } + + @Override + public Map<String, String> getAttributes() { + return Collections.unmodifiableMap(attributes); + } + + @Override + public long getEntryDate() { + return entryDate; + } + + @Override + public long getId() { + return id; + } + + @Override + public long getSize() { + return data.length; + } + + void setData(final byte[] data) { + this.data = data; + } + + byte[] getData() { + return this.data; + } + + @Override + public boolean isPenalized() { + return penalized; + } + + public void putAttributes(final Map<String, String> attrs) { + attributes.putAll(attrs); + } + + public void removeAttributes(final Set<String> attrNames) { + for (final String attrName : attrNames) { + attributes.remove(attrName); + } + } + + @Override + public String toString() { + return "FlowFile[" + id + "," + getAttribute(CoreAttributes.FILENAME.key()) + "," + getSize() + "B]"; + } + + @Override + public int hashCode() { + return (int) id; + } + + @Override + public boolean equals(final Object obj) { + if (obj == null) { + return false; + } + if (obj instanceof MockFlowFile) { + return ((MockFlowFile) obj).id == this.id; + } + return false; + } + + public void assertAttributeExists(final String attributeName) { + Assert.assertTrue("Attribute " + attributeName + " does not exist", attributes.containsKey(attributeName)); + } + + public void assertAttributeNotExists(final String attributeName) { + Assert.assertFalse("Attribute " + attributeName + " not exists with value " + attributes.get(attributeName), + attributes.containsKey(attributeName)); + } + + public void assertAttributeEquals(final String attributeName, final String expectedValue) { + Assert.assertEquals(expectedValue, attributes.get(attributeName)); + } + + public void assertAttributeNotEquals(final String attributeName, final String expectedValue) { + Assert.assertNotSame(expectedValue, attributes.get(attributeName)); + } + + /** + * Asserts that the content of this FlowFile is the same as the content of + * the given file + * + * @param file to compare content against + * @throws IOException if fails doing IO during comparison + */ + public void assertContentEquals(final File file) throws IOException { + assertContentEquals(file.toPath()); + } + + /** + * Asserts that the content of this FlowFile is the same as the content of + * the given path + * + * @param path where to find content to compare to + * @throws IOException if io error occurs while comparing content + */ + public void assertContentEquals(final Path path) throws IOException { + try (final InputStream in = Files.newInputStream(path, StandardOpenOption.READ)) { + assertContentEquals(in); + } + } + + /** + * Asserts that the content of this FlowFile is the same as the content of + * the given byte array + * + * @param data the data to compare + * @throws IOException if any ioe occurs while reading flowfile + */ + public void assertContentEquals(final byte[] data) throws IOException { + try (final InputStream in = new ByteArrayInputStream(data)) { + assertContentEquals(in); + } + } + + public void assertContentEquals(final String data) { + assertContentEquals(data, "UTF-8"); + } + + public void assertContentEquals(final String data, final String charset) { + assertContentEquals(data, Charset.forName(charset)); + } + + public void assertContentEquals(final String data, final Charset charset) { + final String value = new String(this.data, charset); + Assert.assertEquals(data, value); + } + + /** + * Asserts that the content of this FlowFile is the same as the content of + * the given InputStream. This method closes the InputStream when it is + * finished. + * + * @param in the stream to source comparison data from + * @throws IOException if any issues reading from given source + */ + public void assertContentEquals(final InputStream in) throws IOException { + int bytesRead = 0; + try (final BufferedInputStream buffered = new BufferedInputStream(in)) { + for (int i = 0; i < data.length; i++) { + final int fromStream = buffered.read(); + if (fromStream < 0) { + Assert.fail("FlowFile content is " + data.length + " bytes but provided input is only " + bytesRead + " bytes"); + } + + if ((fromStream & 0xFF) != (data[i] & 0xFF)) { + Assert.fail("FlowFile content differs from input at byte " + bytesRead + " with input having value " + + (fromStream & 0xFF) + " and FlowFile having value " + (data[i] & 0xFF)); + } + + bytesRead++; + } + + final int nextByte = buffered.read(); + if (nextByte >= 0) { + Assert.fail("Contents of input and FlowFile were the same through byte " + data.length + "; however, FlowFile's content ended at this point, and input has more data"); + } + } + } + + /** + * @return a copy of the the contents of the FlowFile as a byte array + */ + public byte[] toByteArray() { + return Arrays.copyOf(this.data, this.data.length); + } + + @Override + public Long getLastQueueDate() { + return entryDate; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFileQueue.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFileQueue.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFileQueue.java new file mode 100644 index 0000000..775a1d5 --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockFlowFileQueue.java @@ -0,0 +1,85 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import java.util.Collection; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +import org.apache.nifi.processor.QueueSize; + +public class MockFlowFileQueue { + + private final BlockingQueue<MockFlowFile> queue; + + private final ReadWriteLock rwLock = new ReentrantReadWriteLock(); + private final Lock readLock = rwLock.readLock(); + private final Lock writeLock = rwLock.writeLock(); + + public MockFlowFileQueue() { + queue = new LinkedBlockingQueue<>(); + } + + public void offer(final MockFlowFile flowFile) { + writeLock.lock(); + try { + queue.offer(flowFile); + } finally { + writeLock.unlock(); + } + } + + public MockFlowFile poll() { + writeLock.lock(); + try { + return queue.poll(); + } finally { + writeLock.unlock(); + } + } + + public void addAll(final Collection<MockFlowFile> flowFiles) { + writeLock.lock(); + try { + queue.addAll(flowFiles); + } finally { + writeLock.unlock(); + } + } + + public QueueSize size() { + readLock.lock(); + try { + final int count = queue.size(); + + long contentSize = 0L; + for (final MockFlowFile flowFile : queue) { + contentSize += flowFile.getSize(); + } + return new QueueSize(count, contentSize); + } finally { + readLock.unlock(); + } + } + + public boolean isEmpty() { + return size().getObjectCount() == 0; + } +} http://git-wip-us.apache.org/repos/asf/nifi/blob/aa998847/nifi-mock/src/main/java/org/apache/nifi/util/MockProcessContext.java ---------------------------------------------------------------------- diff --git a/nifi-mock/src/main/java/org/apache/nifi/util/MockProcessContext.java b/nifi-mock/src/main/java/org/apache/nifi/util/MockProcessContext.java new file mode 100644 index 0000000..20a2f7c --- /dev/null +++ b/nifi-mock/src/main/java/org/apache/nifi/util/MockProcessContext.java @@ -0,0 +1,286 @@ +/* + * 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. + */ +package org.apache.nifi.util; + +import static java.util.Objects.requireNonNull; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; + +import org.apache.nifi.components.ConfigurableComponent; +import org.apache.nifi.components.PropertyDescriptor; +import org.apache.nifi.components.PropertyValue; +import org.apache.nifi.components.ValidationResult; +import org.apache.nifi.controller.ControllerService; +import org.apache.nifi.controller.ControllerServiceLookup; +import org.apache.nifi.processor.Processor; +import org.apache.nifi.processor.Relationship; +import org.apache.nifi.processor.SchedulingContext; +import org.junit.Assert; + +public class MockProcessContext extends MockControllerServiceLookup implements SchedulingContext, ControllerServiceLookup { + + private final ConfigurableComponent component; + private final Map<PropertyDescriptor, String> properties = new HashMap<>(); + + private String annotationData = null; + private boolean yieldCalled = false; + private boolean enableExpressionValidation = false; + private boolean allowExpressionValidation = true; + + private volatile Set<Relationship> unavailableRelationships = new HashSet<>(); + + /** + * Creates a new MockProcessContext for the given Processor + * + * @param component being mocked + */ + public MockProcessContext(final ConfigurableComponent component) { + this.component = Objects.requireNonNull(component); + } + + public MockProcessContext(final ControllerService component, final MockProcessContext context) { + this(component); + + try { + annotationData = context.getControllerServiceAnnotationData(component); + final Map<PropertyDescriptor, String> props = context.getControllerServiceProperties(component); + properties.putAll(props); + + super.addControllerServices(context); + } catch (IllegalArgumentException e) { + // do nothing...the service is being loaded + } + } + + @Override + public PropertyValue getProperty(final PropertyDescriptor descriptor) { + return getProperty(descriptor.getName()); + } + + @Override + public PropertyValue getProperty(final String propertyName) { + final PropertyDescriptor descriptor = component.getPropertyDescriptor(propertyName); + if (descriptor == null) { + return null; + } + + final String setPropertyValue = properties.get(descriptor); + final String propValue = (setPropertyValue == null) ? descriptor.getDefaultValue() : setPropertyValue; + return new MockPropertyValue(propValue, this, (enableExpressionValidation && allowExpressionValidation) ? descriptor : null); + } + + @Override + public PropertyValue newPropertyValue(final String rawValue) { + return new MockPropertyValue(rawValue, this); + } + + public ValidationResult setProperty(final String propertyName, final String propertyValue) { + return setProperty(new PropertyDescriptor.Builder().name(propertyName).build(), propertyValue); + } + + /** + * Updates the value of the property with the given PropertyDescriptor to + * the specified value IF and ONLY IF the value is valid according to the + * descriptor's validator. Otherwise, the property value is not updated. In + * either case, the ValidationResult is returned, indicating whether or not + * the property is valid + * + * @param descriptor of property to modify + * @param value new value + * @return result + */ + public ValidationResult setProperty(final PropertyDescriptor descriptor, final String value) { + requireNonNull(descriptor); + requireNonNull(value, "Cannot set property to null value; if the intent is to remove the property, call removeProperty instead"); + final PropertyDescriptor fullyPopulatedDescriptor = component.getPropertyDescriptor(descriptor.getName()); + + final ValidationResult result = fullyPopulatedDescriptor.validate(value, new MockValidationContext(this)); + String oldValue = properties.put(fullyPopulatedDescriptor, value); + if (oldValue == null) { + oldValue = fullyPopulatedDescriptor.getDefaultValue(); + } + if ((value == null && oldValue != null) || (value != null && !value.equals(oldValue))) { + component.onPropertyModified(fullyPopulatedDescriptor, oldValue, value); + } + + return result; + } + + public boolean removeProperty(final PropertyDescriptor descriptor) { + Objects.requireNonNull(descriptor); + final PropertyDescriptor fullyPopulatedDescriptor = component.getPropertyDescriptor(descriptor.getName()); + String value = null; + if (!fullyPopulatedDescriptor.isRequired() && (value = properties.remove(fullyPopulatedDescriptor)) != null) { + component.onPropertyModified(fullyPopulatedDescriptor, value, null); + return true; + } + return false; + } + + @Override + public void yield() { + yieldCalled = true; + } + + public boolean isYieldCalled() { + return yieldCalled; + } + + public void addControllerService(final String serviceIdentifier, final ControllerService controllerService, final Map<PropertyDescriptor, String> properties, final String annotationData) { + requireNonNull(controllerService); + final ControllerServiceConfiguration config = addControllerService(controllerService); + config.setProperties(properties); + config.setAnnotationData(annotationData); + } + + @Override + public int getMaxConcurrentTasks() { + return 1; + } + + public void setAnnotationData(final String annotationData) { + this.annotationData = annotationData; + } + + @Override + public String getAnnotationData() { + return annotationData; + } + + @Override + public Map<PropertyDescriptor, String> getProperties() { + final List<PropertyDescriptor> supported = component.getPropertyDescriptors(); + if (supported == null || supported.isEmpty()) { + return Collections.unmodifiableMap(properties); + } else { + final Map<PropertyDescriptor, String> props = new LinkedHashMap<>(); + for (final PropertyDescriptor descriptor : supported) { + props.put(descriptor, null); + } + props.putAll(properties); + return props; + } + } + + /** + * Validates the current properties, returning ValidationResults for any + * invalid properties. All processor defined properties will be validated. + * If they are not included in the in the purposed configuration, the + * default value will be used. + * + * @return Collection of validation result objects for any invalid findings + * only. If the collection is empty then the processor is valid. Guaranteed + * non-null + */ + public Collection<ValidationResult> validate() { + return component.validate(new MockValidationContext(this)); + } + + public boolean isValid() { + for (final ValidationResult result : validate()) { + if (!result.isValid()) { + return false; + } + } + + return true; + } + + public void assertValid() { + final StringBuilder sb = new StringBuilder(); + int failureCount = 0; + + for (final ValidationResult result : validate()) { + if (!result.isValid()) { + sb.append(result.toString()).append("\n"); + failureCount++; + } + } + + if (failureCount > 0) { + Assert.fail("Processor has " + failureCount + " validation failures:\n" + sb.toString()); + } + } + + @Override + public String encrypt(final String unencrypted) { + return "enc{" + unencrypted + "}"; + } + + @Override + public String decrypt(final String encrypted) { + if (encrypted.startsWith("enc{") && encrypted.endsWith("}")) { + return encrypted.substring(4, encrypted.length() - 2); + } + return encrypted; + } + + public void setValidateExpressionUsage(final boolean validate) { + allowExpressionValidation = validate; + } + + public void enableExpressionValidation() { + enableExpressionValidation = true; + } + + public void disableExpressionValidation() { + enableExpressionValidation = false; + } + + Map<PropertyDescriptor, String> getControllerServiceProperties(final ControllerService controllerService) { + return super.getConfiguration(controllerService.getIdentifier()).getProperties(); + } + + String getControllerServiceAnnotationData(final ControllerService controllerService) { + return super.getConfiguration(controllerService.getIdentifier()).getAnnotationData(); + } + + @Override + public ControllerServiceLookup getControllerServiceLookup() { + return this; + } + + @Override + public void leaseControllerService(final String identifier) { + } + + public Set<Relationship> getAvailableRelationships() { + if (!(component instanceof Processor)) { + return Collections.emptySet(); + } + + final Set<Relationship> relationships = new HashSet<>(((Processor) component).getRelationships()); + relationships.removeAll(unavailableRelationships); + return relationships; + } + + public void setUnavailableRelationships(final Set<Relationship> relationships) { + this.unavailableRelationships = Collections.unmodifiableSet(new HashSet<>(relationships)); + } + + public Set<Relationship> getUnavailableRelationships() { + return unavailableRelationships; + } +}
