Repository: nifi-registry Updated Branches: refs/heads/master a520c7575 -> 7dd88eb44
http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/main/java/org/apache/nifi/registry/metadata/MetadataHolder.java ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/main/java/org/apache/nifi/registry/metadata/MetadataHolder.java b/nifi-registry-provider-impl/src/main/java/org/apache/nifi/registry/metadata/MetadataHolder.java new file mode 100644 index 0000000..6ce3dfb --- /dev/null +++ b/nifi-registry-provider-impl/src/main/java/org/apache/nifi/registry/metadata/MetadataHolder.java @@ -0,0 +1,141 @@ +/* + * 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.registry.metadata; + +import org.apache.nifi.registry.bucket.Bucket; +import org.apache.nifi.registry.flow.VersionedFlow; +import org.apache.nifi.registry.flow.VersionedFlowSnapshot; +import org.apache.nifi.registry.metadata.generated.Buckets; +import org.apache.nifi.registry.metadata.generated.Flow; +import org.apache.nifi.registry.metadata.generated.Flows; +import org.apache.nifi.registry.metadata.generated.Metadata; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Provides atomic access to the Metadata object. + */ +public class MetadataHolder { + + private final Metadata metadata; + private final Map<String,Bucket> bucketsById; + private final Map<String,VersionedFlow> flowsById; + private final Map<String,Set<VersionedFlow>> flowsByBucket; + + public MetadataHolder(final Metadata metadata) { + this.metadata = metadata; + this.bucketsById = Collections.unmodifiableMap(createBucketsBydId(metadata)); + this.flowsByBucket = Collections.unmodifiableMap(createFlowsByBucket(metadata)); + this.flowsById = Collections.unmodifiableMap(createFlowsById(flowsByBucket)); + } + + private Map<String,Bucket> createBucketsBydId(final Metadata metadata) { + final Map<String,Bucket> bucketsById = new HashMap<>(); + + final Buckets buckets = metadata.getBuckets(); + if (buckets != null) { + buckets.getBucket().stream().forEach(b -> bucketsById.put(b.getIdentifier(), createBucket(b))); + } + + return bucketsById; + } + + private Bucket createBucket(final org.apache.nifi.registry.metadata.generated.Bucket jaxbBucket) { + final Bucket bucket = new Bucket(); + bucket.setIdentifier(jaxbBucket.getIdentifier()); + bucket.setName(jaxbBucket.getName()); + bucket.setDescription(jaxbBucket.getDescription()); + bucket.setCreatedTimestamp(jaxbBucket.getCreatedTimestamp()); + return bucket; + } + + private Map<String,Set<VersionedFlow>> createFlowsByBucket(final Metadata metadata) { + final Map<String,Set<VersionedFlow>> flowsByBucket = new HashMap<>(); + + final Flows flows = metadata.getFlows(); + if (flows != null) { + flows.getFlow().stream().forEach(f -> { + Set<VersionedFlow> bucketFLows = flowsByBucket.get(f.getBucketIdentifier()); + if (bucketFLows == null) { + bucketFLows = new HashSet<>(); + flowsByBucket.put(f.getBucketIdentifier(), bucketFLows); + } + bucketFLows.add(createFlow(f)); + }); + } + + return flowsByBucket; + } + + private VersionedFlow createFlow(final Flow flow) { + final VersionedFlow versionedFlow = new VersionedFlow(); + versionedFlow.setIdentifier(flow.getIdentifier()); + versionedFlow.setName(flow.getName()); + versionedFlow.setDescription(flow.getDescription()); + versionedFlow.setCreatedTimestamp(flow.getCreatedTimestamp()); + versionedFlow.setModifiedTimestamp(flow.getModifiedTimestamp()); + + if (flow.getSnapshot() != null) { + flow.getSnapshot().stream().forEach(s -> versionedFlow.addVersionedFlowSnapshot(createSnapshot(flow, s))); + } + + return versionedFlow; + } + + private VersionedFlowSnapshot createSnapshot(final Flow flow, final Flow.Snapshot snapshot) { + final VersionedFlowSnapshot versionedFlowSnapshot = new VersionedFlowSnapshot(); + versionedFlowSnapshot.setFlowIdentifier(flow.getIdentifier()); + versionedFlowSnapshot.setFlowName(flow.getName()); + versionedFlowSnapshot.setVersion(snapshot.getVersion()); + versionedFlowSnapshot.setComments(snapshot.getComments()); + versionedFlowSnapshot.setTimestamp(snapshot.getCreatedTimestamp()); + return versionedFlowSnapshot; + } + + private Map<String,VersionedFlow> createFlowsById(final Map<String,Set<VersionedFlow>> flowsByBucket) { + final Map<String,VersionedFlow> flowsBdId = new HashMap<>(); + + for (final Map.Entry<String,Set<VersionedFlow>> entry : flowsByBucket.entrySet()) { + for (final VersionedFlow flow : entry.getValue()) { + flowsBdId.put(flow.getIdentifier(), flow); + } + } + + return flowsBdId; + } + + public Metadata getMetadata() { + return metadata; + } + + public Map<String,Bucket> getBucketsBydId() { + return bucketsById; + } + + public Map<String,VersionedFlow> getFlowsById() { + return flowsById; + } + + public Map<String,Set<VersionedFlow>> getFlowsByBucket() { + return flowsByBucket; + } + +} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/main/xsd/metadata.xsd ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/main/xsd/metadata.xsd b/nifi-registry-provider-impl/src/main/xsd/metadata.xsd new file mode 100644 index 0000000..7f71745 --- /dev/null +++ b/nifi-registry-provider-impl/src/main/xsd/metadata.xsd @@ -0,0 +1,139 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> + + <!-- Buckets --> + + <xs:complexType name="Bucket"> + <xs:sequence> + <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + <xs:attribute name="identifier"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:pattern value=".*[^\s].*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="name"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:pattern value=".*[^\s].*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="createdTimestamp"> + <xs:simpleType> + <xs:restriction base="xs:long"> + <xs:minInclusive value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + + <xs:complexType name="Buckets"> + <xs:sequence> + <xs:element name="bucket" type="Bucket" minOccurs="0" maxOccurs="unbounded"/> + </xs:sequence> + </xs:complexType> + + <!-- Flows --> + + <xs:complexType name="Flow"> + <xs:sequence> + <xs:element name="description" type="xs:string" minOccurs="0" maxOccurs="1"/> + <xs:element name="snapshot" minOccurs="0" maxOccurs="unbounded" > + <xs:complexType> + <xs:sequence> + <xs:element name="comments" type="xs:string" minOccurs="0" maxOccurs="1"/> + </xs:sequence> + <xs:attribute name="version"> + <xs:simpleType> + <xs:restriction base="xs:int"> + <xs:minInclusive value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="createdTimestamp"> + <xs:simpleType> + <xs:restriction base="xs:long"> + <xs:minInclusive value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + </xs:element> + </xs:sequence> + <xs:attribute name="identifier"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:pattern value=".*[^\s].*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="name"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:pattern value=".*[^\s].*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="createdTimestamp"> + <xs:simpleType> + <xs:restriction base="xs:long"> + <xs:minInclusive value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="modifiedTimestamp"> + <xs:simpleType> + <xs:restriction base="xs:long"> + <xs:minInclusive value="1"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="bucketIdentifier"> + <xs:simpleType> + <xs:restriction base="xs:string"> + <xs:minLength value="1"/> + <xs:pattern value=".*[^\s].*"/> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + </xs:complexType> + + <xs:complexType name="Flows"> + <xs:sequence> + <xs:element name="flow" type="Flow" minOccurs="0" maxOccurs="unbounded" /> + </xs:sequence> + </xs:complexType> + + <!-- Metadata --> + + <xs:element name="metadata"> + <xs:complexType> + <xs:sequence> + <xs:element name="buckets" type="Buckets" minOccurs="0" maxOccurs="1"/> + <xs:element name="flows" type="Flows" minOccurs="0" maxOccurs="1" /> + </xs:sequence> + </xs:complexType> + </xs:element> + +</xs:schema> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/flow/TestFileSystemFlowPersistenceProvider.java ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/flow/TestFileSystemFlowPersistenceProvider.java b/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/flow/TestFileSystemFlowPersistenceProvider.java new file mode 100644 index 0000000..aa0bf58 --- /dev/null +++ b/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/flow/TestFileSystemFlowPersistenceProvider.java @@ -0,0 +1,202 @@ +/* + * 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.registry.flow; + +import org.apache.commons.io.IOUtils; +import org.apache.nifi.registry.provider.ProviderConfigurationContext; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.Map; + +import static org.mockito.Mockito.when; + +public class TestFileSystemFlowPersistenceProvider { + + static final String FLOW_STORAGE_DIR = "target/flow_storage"; + + static final ProviderConfigurationContext CONFIGURATION_CONTEXT = new ProviderConfigurationContext() { + @Override + public Map<String, String> getProperties() { + final Map<String,String> props = new HashMap<>(); + props.put(FileSystemFlowPersistenceProvider.FLOW_STORAGE_DIR_PROP, FLOW_STORAGE_DIR); + return props; + } + }; + + private File flowStorageDir; + private FileSystemFlowPersistenceProvider fileSystemFlowProvider; + + @Before + public void setup() throws IOException { + flowStorageDir = new File(FLOW_STORAGE_DIR); + if (flowStorageDir.exists()) { + org.apache.commons.io.FileUtils.cleanDirectory(flowStorageDir); + flowStorageDir.delete(); + } + + Assert.assertFalse(flowStorageDir.exists()); + + fileSystemFlowProvider = new FileSystemFlowPersistenceProvider(); + fileSystemFlowProvider.onConfigured(CONFIGURATION_CONTEXT); + Assert.assertTrue(flowStorageDir.exists()); + } + + @Test + public void testSaveSuccessfully() throws IOException { + createAndSaveSnapshot(fileSystemFlowProvider,"bucket1", "flow1", 1, "flow1v1"); + verifySnapshot(flowStorageDir, "bucket1", "flow1", 1, "flow1v1"); + + createAndSaveSnapshot(fileSystemFlowProvider,"bucket1", "flow1", 2, "flow1v2"); + verifySnapshot(flowStorageDir, "bucket1", "flow1", 2, "flow1v2"); + + createAndSaveSnapshot(fileSystemFlowProvider,"bucket1", "flow2", 1, "flow2v1"); + verifySnapshot(flowStorageDir, "bucket1", "flow2", 1, "flow2v1"); + + createAndSaveSnapshot(fileSystemFlowProvider,"bucket2", "flow3", 1, "flow3v1"); + verifySnapshot(flowStorageDir, "bucket2", "flow3", 1, "flow3v1"); + } + + @Test + public void testSaveWithExistingVersion() throws IOException { + final FlowSnapshotContext context = Mockito.mock(FlowSnapshotContext.class); + when(context.getBucketId()).thenReturn("bucket1"); + when(context.getFlowId()).thenReturn("flow1"); + when(context.getVersion()).thenReturn(1); + + final byte[] content = "flow1v1".getBytes(StandardCharsets.UTF_8); + fileSystemFlowProvider.saveSnapshot(context, content); + + // save new content for an existing version + final byte[] content2 = "XXX".getBytes(StandardCharsets.UTF_8); + try { + fileSystemFlowProvider.saveSnapshot(context, content2); + Assert.fail("Should have thrown exception"); + } catch (Exception e) { + + } + + // verify the new content wasn't written + final File flowSnapshotFile = new File(flowStorageDir, "bucket1/flow1/1/1" + FileSystemFlowPersistenceProvider.SNAPSHOT_EXTENSION); + try (InputStream in = new FileInputStream(flowSnapshotFile)) { + Assert.assertEquals("flow1v1", IOUtils.toString(in, StandardCharsets.UTF_8)); + } + } + + @Test + public void testSaveAndGet() throws IOException { + createAndSaveSnapshot(fileSystemFlowProvider,"bucket1", "flow1", 1, "flow1v1"); + createAndSaveSnapshot(fileSystemFlowProvider,"bucket1", "flow1", 2, "flow1v2"); + + final byte[] flow1v1 = fileSystemFlowProvider.getSnapshot("bucket1", "flow1", 1); + Assert.assertEquals("flow1v1", new String(flow1v1, StandardCharsets.UTF_8)); + + final byte[] flow1v2 = fileSystemFlowProvider.getSnapshot("bucket1", "flow1", 2); + Assert.assertEquals("flow1v2", new String(flow1v2, StandardCharsets.UTF_8)); + } + + @Test + public void testGetWhenDoesNotExist() { + final byte[] flow1v1 = fileSystemFlowProvider.getSnapshot("bucket1", "flow1", 1); + Assert.assertNull(flow1v1); + } + + @Test + public void testDeleteSnapshots() throws IOException { + final String bucketId = "bucket1"; + final String flowId = "flow1"; + + createAndSaveSnapshot(fileSystemFlowProvider, bucketId, flowId, 1, "flow1v1"); + createAndSaveSnapshot(fileSystemFlowProvider, bucketId, flowId, 2, "flow1v2"); + + Assert.assertNotNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 1)); + Assert.assertNotNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 2)); + + fileSystemFlowProvider.deleteSnapshots(bucketId, flowId); + + Assert.assertNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 1)); + Assert.assertNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 2)); + + // delete a flow that doesn't exist + fileSystemFlowProvider.deleteSnapshots(bucketId, "some-other-flow"); + + // delete a bucket that doesn't exist + fileSystemFlowProvider.deleteSnapshots("some-other-bucket", flowId); + } + + @Test + public void testDeleteSnapshot() throws IOException { + final String bucketId = "bucket1"; + final String flowId = "flow1"; + + createAndSaveSnapshot(fileSystemFlowProvider, bucketId, flowId, 1, "flow1v1"); + createAndSaveSnapshot(fileSystemFlowProvider, bucketId, flowId, 2, "flow1v2"); + + Assert.assertNotNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 1)); + Assert.assertNotNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 2)); + + fileSystemFlowProvider.deleteSnapshot(bucketId, flowId, 1); + + Assert.assertNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 1)); + Assert.assertNotNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 2)); + + fileSystemFlowProvider.deleteSnapshot(bucketId, flowId, 2); + + Assert.assertNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 1)); + Assert.assertNull(fileSystemFlowProvider.getSnapshot(bucketId, flowId, 2)); + + // delete a version that doesn't exist + fileSystemFlowProvider.deleteSnapshot(bucketId, flowId, 3); + + // delete a flow that doesn't exist + fileSystemFlowProvider.deleteSnapshot(bucketId, "some-other-flow", 1); + + // delete a bucket that doesn't exist + fileSystemFlowProvider.deleteSnapshot("some-other-bucket", flowId, 1); + } + + private void createAndSaveSnapshot(final FlowPersistenceProvider flowPersistenceProvider, final String bucketId, final String flowId, final int version, + final String contentString) throws IOException { + final FlowSnapshotContext context = Mockito.mock(FlowSnapshotContext.class); + when(context.getBucketId()).thenReturn(bucketId); + when(context.getFlowId()).thenReturn(flowId); + when(context.getVersion()).thenReturn(version); + + final byte[] content = contentString.getBytes(StandardCharsets.UTF_8); + flowPersistenceProvider.saveSnapshot(context, content); + } + + private void verifySnapshot(final File flowStorageDir, final String bucketId, final String flowId, final int version, + final String contentString) throws IOException { + // verify the correct snapshot file was created + final File flowSnapshotFile = new File(flowStorageDir, + bucketId + "/" + flowId + "/" + version + "/" + version + FileSystemFlowPersistenceProvider.SNAPSHOT_EXTENSION); + Assert.assertTrue(flowSnapshotFile.exists()); + + try (InputStream in = new FileInputStream(flowSnapshotFile)) { + Assert.assertEquals(contentString, IOUtils.toString(in, StandardCharsets.UTF_8)); + } + } +} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/metadata/TestFileSystemMetadataProvider.java ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/metadata/TestFileSystemMetadataProvider.java b/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/metadata/TestFileSystemMetadataProvider.java new file mode 100644 index 0000000..a0d6eb5 --- /dev/null +++ b/nifi-registry-provider-impl/src/test/java/org/apache/nifi/registry/metadata/TestFileSystemMetadataProvider.java @@ -0,0 +1,454 @@ +/* + * 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.registry.metadata; + +import org.apache.nifi.registry.bucket.Bucket; +import org.apache.nifi.registry.flow.VersionedFlow; +import org.apache.nifi.registry.flow.VersionedFlowSnapshot; +import org.apache.nifi.registry.provider.ProviderConfigurationContext; +import org.apache.nifi.registry.provider.ProviderCreationException; +import org.apache.nifi.registry.util.FileUtils; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.StandardCopyOption; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +public class TestFileSystemMetadataProvider { + + static final String METADATA_EMPTY = "metadata-empty.xml"; + static final String METADATA_EMPTY_CONCISE = "metadata-empty-concise.xml"; + static final String METADATA_EXISTING = "metadata-existing.xml"; + static final String METADATA_NEW_FILE = "metadata-test.xml"; + + static final File METADATA_SRC_DIR = new File("src/test/resources/metadata"); + static final File METADATA_DEST_DIR = new File("target/metadata"); + + static final File METADATA_SRC_EMPTY = new File(METADATA_SRC_DIR, METADATA_EMPTY); + static final File METADATA_SRC_EMPTY_CONCISE = new File(METADATA_SRC_DIR, METADATA_EMPTY_CONCISE); + static final File METADATA_SRC_EXISTING = new File(METADATA_SRC_DIR, METADATA_EXISTING); + + static final File METADATA_DEST_EMPTY = new File(METADATA_DEST_DIR, METADATA_EMPTY); + static final File METADATA_DEST_EMPTY_CONCISE = new File(METADATA_DEST_DIR, METADATA_EMPTY_CONCISE); + static final File METADATA_DEST_EXISTING = new File(METADATA_DEST_DIR, METADATA_EXISTING); + static final File METADATA_DEST_NEW_FILE = new File(METADATA_DEST_DIR, METADATA_NEW_FILE); + + private MetadataProvider metadataProvider; + + @Before + public void setup() throws IOException { + FileUtils.ensureDirectoryExistAndCanReadAndWrite(METADATA_DEST_DIR); + org.apache.commons.io.FileUtils.cleanDirectory(METADATA_DEST_DIR); + + Files.copy(METADATA_SRC_EMPTY.toPath(), METADATA_DEST_EMPTY.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.copy(METADATA_SRC_EMPTY_CONCISE.toPath(), METADATA_DEST_EMPTY_CONCISE.toPath(), StandardCopyOption.REPLACE_EXISTING); + Files.copy(METADATA_SRC_EXISTING.toPath(), METADATA_DEST_EXISTING.toPath(), StandardCopyOption.REPLACE_EXISTING); + + metadataProvider = new FileSystemMetadataProvider(); + } + + private ProviderConfigurationContext createConfigContext(final File metadataFile) { + return () -> { + final Map<String,String> props = new HashMap<>(); + props.put(FileSystemMetadataProvider.METADATA_FILE_PROP, metadataFile.getAbsolutePath()); + return props; + }; + } + + @Test(expected = ProviderCreationException.class) + public void testOnConfiguredMissingMetadataFileProperty() { + metadataProvider.onConfigured(() -> new HashMap<>()); + } + + @Test(expected = ProviderCreationException.class) + public void testOnConfiguredBlankMetadataFileProperty() { + metadataProvider.onConfigured(() -> { + final Map<String,String> props = new HashMap<>(); + props.put(FileSystemMetadataProvider.METADATA_FILE_PROP, " "); + return props; + }); + } + + @Test + public void testOnConfiguredWithEmptyMetadata() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EMPTY)); + assertEquals(0, metadataProvider.getBuckets().size()); + assertEquals(0, metadataProvider.getFlows().size()); + } + + @Test + public void testOnConfiguredWithEmptyConciseMetadata() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EMPTY_CONCISE)); + assertEquals(0, metadataProvider.getBuckets().size()); + assertEquals(0, metadataProvider.getFlows().size()); + } + + @Test + public void testOnConfiguredWithExistingMetadata() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + assertEquals(1, metadataProvider.getFlows().size()); + + final Bucket bucket1 = metadataProvider.getBucket("bucket1"); + assertNotNull(bucket1); + assertEquals("bucket1", bucket1.getIdentifier()); + + final Bucket bucket2 = metadataProvider.getBucket("bucket2"); + assertNotNull(bucket2); + assertEquals("bucket2", bucket2.getIdentifier()); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + assertEquals("flow1", versionedFlow.getIdentifier()); + } + + @Test(expected = IllegalArgumentException.class) + public void testCreateNullBucket() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_NEW_FILE)); + metadataProvider.createBucket(null); + } + + @Test + public void testCreateBucket() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_NEW_FILE)); + + final Bucket bucket = new Bucket(); + bucket.setIdentifier("bucket1"); + bucket.setName("My Bucket"); + bucket.setDescription("This is my bucket"); + bucket.setCreatedTimestamp(System.currentTimeMillis()); + + final Bucket returnedBucket = metadataProvider.createBucket(bucket); + assertNotNull(returnedBucket); + assertEquals(bucket.getIdentifier(), returnedBucket.getIdentifier()); + assertEquals(bucket.getName(), returnedBucket.getName()); + assertEquals(bucket.getDescription(), returnedBucket.getDescription()); + assertEquals(bucket.getCreatedTimestamp(), returnedBucket.getCreatedTimestamp()); + } + + @Test + public void testGetBucketExists() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + final Bucket bucket1 = metadataProvider.getBucket("bucket1"); + assertNotNull(bucket1); + assertEquals("bucket1", bucket1.getIdentifier()); + assertEquals("Bryan's Bucket", bucket1.getName()); + assertEquals("The description for Bryan's Bucket.", bucket1.getDescription()); + assertEquals(111111111, bucket1.getCreatedTimestamp()); + } + + @Test + public void testGetBucketDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + final Bucket bucket1 = metadataProvider.getBucket("bucket-does-not-exist"); + assertNull(bucket1); + } + + @Test + public void testUpdateBucketExists() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + final Bucket bucket = metadataProvider.getBucket("bucket1"); + assertNotNull(bucket); + + bucket.setName("New Name"); + bucket.setDescription("New Description"); + + final Bucket updatedBucket = metadataProvider.updateBucket(bucket); + assertNotNull(updatedBucket); + assertEquals("New Name", updatedBucket.getName()); + assertEquals("New Description", updatedBucket.getDescription()); + } + + @Test + public void testUpdateBucketDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + final Bucket bucket = new Bucket(); + bucket.setIdentifier("does-not-exist"); + bucket.setName("My Bucket"); + bucket.setDescription("This is my bucket"); + bucket.setCreatedTimestamp(System.currentTimeMillis()); + + final Bucket updatedBucket = metadataProvider.updateBucket(bucket); + assertNull(updatedBucket); + } + + @Test + public void testDeleteBucketWithFlows() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + final String bucketId = "bucket1"; + assertNotNull(metadataProvider.getBucket(bucketId)); + + final Set<VersionedFlow> bucketFlows = metadataProvider.getFlows(bucketId); + assertNotNull(bucketFlows); + assertEquals(1, bucketFlows.size()); + + metadataProvider.deleteBucket(bucketId); + assertNull(metadataProvider.getBucket(bucketId)); + + final Set<VersionedFlow> bucketFlows2 = metadataProvider.getFlows(bucketId); + assertNotNull(bucketFlows2); + assertEquals(0, bucketFlows2.size()); + } + + @Test + public void testDeleteBucketDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + final String bucketId = "bucket-does-not-exist"; + metadataProvider.deleteBucket(bucketId); + + assertEquals(2, metadataProvider.getBuckets().size()); + } + + @Test + public void testCreateFlow() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + assertEquals(2, metadataProvider.getBuckets().size()); + + // verify bucket2 exists and has no flows + final Bucket bucket2 = metadataProvider.getBucket("bucket2"); + assertNotNull(bucket2); + assertEquals(0, metadataProvider.getFlows(bucket2.getIdentifier()).size()); + + final VersionedFlow versionedFlow = new VersionedFlow(); + versionedFlow.setIdentifier("flow2"); + versionedFlow.setName("New Flow"); + versionedFlow.setDescription("This is a new flow"); + versionedFlow.setCreatedTimestamp(System.currentTimeMillis()); + versionedFlow.setModifiedTimestamp(System.currentTimeMillis()); + + final VersionedFlow createdFlow = metadataProvider.createFlow(bucket2.getIdentifier(), versionedFlow); + assertNotNull(createdFlow); + assertEquals(versionedFlow.getIdentifier(), createdFlow.getIdentifier()); + assertEquals(versionedFlow.getName(), createdFlow.getName()); + assertEquals(versionedFlow.getDescription(), createdFlow.getDescription()); + assertEquals(versionedFlow.getCreatedTimestamp(), createdFlow.getCreatedTimestamp()); + assertEquals(versionedFlow.getModifiedTimestamp(), createdFlow.getModifiedTimestamp()); + + assertEquals(1, metadataProvider.getFlows(bucket2.getIdentifier()).size()); + } + + @Test + public void testGetFlowExists() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + assertEquals("flow1", versionedFlow.getIdentifier()); + assertEquals("Bryan's Flow", versionedFlow.getName()); + assertEquals("The description for Bryan's Flow.", versionedFlow.getDescription()); + assertEquals(333333333, versionedFlow.getCreatedTimestamp()); + assertEquals(444444444, versionedFlow.getModifiedTimestamp()); + assertEquals(3, versionedFlow.getSnapshots().size()); + } + + @Test + public void testGetFlowDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow-does-not-exist"); + assertNull(versionedFlow); + } + + @Test + public void testUpdateFlowExists() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + + final String newFlowName = "New Flow Name"; + final String newFlowDescription = "New Flow Description"; + assertNotEquals(versionedFlow.getName(), newFlowName); + assertNotEquals(versionedFlow.getDescription(), newFlowDescription); + + versionedFlow.setName("New Flow Name"); + versionedFlow.setDescription("New Flow Description"); + + final VersionedFlow updatedFlow = metadataProvider.updateFlow(versionedFlow); + assertEquals(newFlowName, updatedFlow.getName()); + assertEquals(newFlowDescription, updatedFlow.getDescription()); + assertEquals(versionedFlow.getCreatedTimestamp(), updatedFlow.getCreatedTimestamp()); + assertTrue(updatedFlow.getModifiedTimestamp() > versionedFlow.getModifiedTimestamp()); + } + + @Test + public void testUpdateFlowDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = new VersionedFlow(); + versionedFlow.setIdentifier("does-not-exist"); + versionedFlow.setName("Does Not Exist"); + versionedFlow.setDescription("Does Not Exist"); + versionedFlow.setCreatedTimestamp(System.currentTimeMillis()); + versionedFlow.setModifiedTimestamp(System.currentTimeMillis()); + + final VersionedFlow updatedFlow = metadataProvider.updateFlow(versionedFlow); + assertNull(updatedFlow); + } + + @Test + public void testDeleteFlowWithSnapshots() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + assertNotNull(versionedFlow.getSnapshots()); + assertTrue(versionedFlow.getSnapshots().size() > 0); + + metadataProvider.deleteFlow(versionedFlow.getIdentifier()); + + final VersionedFlow deletedFlow = metadataProvider.getFlow("flow1"); + assertNull(deletedFlow); + } + + @Test + public void testDeleteFlowDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + assertEquals(1, metadataProvider.getFlows().size()); + metadataProvider.deleteFlow("does-not-exist"); + assertEquals(1, metadataProvider.getFlows().size()); + } + + @Test + public void testCreateFlowSnapshot() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + assertNotNull(versionedFlow.getSnapshots()); + + int lastVersion = 1; + for (final VersionedFlowSnapshot snapshot : versionedFlow.getSnapshots()) { + if (snapshot.getVersion() > lastVersion) { + lastVersion = snapshot.getVersion(); + } + } + + final VersionedFlowSnapshot nextSnapshot = new VersionedFlowSnapshot(); + nextSnapshot.setFlowIdentifier(versionedFlow.getIdentifier()); + nextSnapshot.setFlowName(versionedFlow.getName()); + nextSnapshot.setVersion(lastVersion + 1); + nextSnapshot.setComments("This is the next snapshot"); + nextSnapshot.setTimestamp(System.currentTimeMillis()); + + final VersionedFlowSnapshot createdSnapshot = metadataProvider.createFlowSnapshot(nextSnapshot); + assertEquals(nextSnapshot.getFlowIdentifier(), createdSnapshot.getFlowIdentifier()); + assertEquals(nextSnapshot.getFlowName(), createdSnapshot.getFlowName()); + assertEquals(nextSnapshot.getVersion(), createdSnapshot.getVersion()); + assertEquals(nextSnapshot.getComments(), createdSnapshot.getComments()); + assertEquals(nextSnapshot.getTimestamp(), createdSnapshot.getTimestamp()); + + final VersionedFlow updatedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(updatedFlow); + assertNotNull(updatedFlow.getSnapshots()); + assertEquals(updatedFlow.getSnapshots().size(), versionedFlow.getSnapshots().size() + 1); + } + + @Test + public void testGetFlowSnapshotExists() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlowSnapshot snapshot = metadataProvider.getFlowSnapshot("flow1", 1); + assertNotNull(snapshot); + assertEquals("flow1", snapshot.getFlowIdentifier()); + assertEquals("Bryan's Flow", snapshot.getFlowName()); + assertEquals(1, snapshot.getVersion()); + assertEquals(555555555, snapshot.getTimestamp()); + assertEquals("These are the comments for snapshot #1.", snapshot.getComments()); + } + + @Test + public void testGetFlowSnapshotNameDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlowSnapshot snapshot = metadataProvider.getFlowSnapshot("does-not-exist", 1); + assertNull(snapshot); + } + + @Test + public void testGetFlowSnapshotVersionDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlowSnapshot snapshot = metadataProvider.getFlowSnapshot("flow1", Integer.MAX_VALUE); + assertNull(snapshot); + } + + @Test + public void testDeleteSnapshotExists() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + assertNotNull(versionedFlow.getSnapshots()); + assertEquals(3, versionedFlow.getSnapshots().size()); + + final VersionedFlowSnapshot firstSnapshot = versionedFlow.getSnapshots().stream().findFirst().orElse(null); + assertNotNull(firstSnapshot); + + metadataProvider.deleteFlowSnapshot(versionedFlow.getIdentifier(), firstSnapshot.getVersion()); + + final VersionedFlow updatedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(updatedFlow); + assertNotNull(updatedFlow.getSnapshots()); + assertEquals(2, updatedFlow.getSnapshots().size()); + + final VersionedFlowSnapshot deletedSnapshot = updatedFlow.getSnapshots().stream() + .filter(s -> s.getVersion() == firstSnapshot.getVersion()).findFirst().orElse(null); + assertNull(deletedSnapshot); + } + + @Test + public void testDeleteSnapshotDoesNotExist() { + metadataProvider.onConfigured(createConfigContext(METADATA_DEST_EXISTING)); + + final VersionedFlow versionedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(versionedFlow); + assertNotNull(versionedFlow.getSnapshots()); + assertEquals(3, versionedFlow.getSnapshots().size()); + + metadataProvider.deleteFlowSnapshot(versionedFlow.getIdentifier(), Integer.MAX_VALUE); + + final VersionedFlow updatedFlow = metadataProvider.getFlow("flow1"); + assertNotNull(updatedFlow); + assertNotNull(updatedFlow.getSnapshots()); + assertEquals(3, updatedFlow.getSnapshots().size()); + } +} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty-concise.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty-concise.xml b/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty-concise.xml new file mode 100644 index 0000000..8f4f4f9 --- /dev/null +++ b/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty-concise.xml @@ -0,0 +1,16 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<metadata /> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty.xml b/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty.xml new file mode 100644 index 0000000..5af6f87 --- /dev/null +++ b/nifi-registry-provider-impl/src/test/resources/metadata/metadata-empty.xml @@ -0,0 +1,17 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<metadata> +</metadata> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-provider-impl/src/test/resources/metadata/metadata-existing.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-provider-impl/src/test/resources/metadata/metadata-existing.xml b/nifi-registry-provider-impl/src/test/resources/metadata/metadata-existing.xml new file mode 100644 index 0000000..29db524 --- /dev/null +++ b/nifi-registry-provider-impl/src/test/resources/metadata/metadata-existing.xml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> +<!-- + 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. +--> +<metadata> + <buckets> + <bucket identifier="bucket1" name="Bryan's Bucket" createdTimestamp="111111111"> + <description>The description for Bryan's Bucket.</description> + </bucket> + <bucket identifier="bucket2" name="Matt's Bucket" createdTimestamp="222222222" /> + </buckets> + <flows> + <flow identifier="flow1" name="Bryan's Flow" createdTimestamp="333333333" modifiedTimestamp="444444444" bucketIdentifier="bucket1"> + <description>The description for Bryan's Flow.</description> + <snapshot version="1" createdTimestamp="555555555"> + <comments>These are the comments for snapshot #1.</comments> + </snapshot> + <snapshot version="2" createdTimestamp="666666666" /> + <snapshot version="3" createdTimestamp="777777777"> + <comments>These are the comments for snapshot #3.</comments> + </snapshot> + </flow> + </flows> +</metadata> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties ---------------------------------------------------------------------- diff --git a/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties b/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties index 156db2e..a748f2f 100644 --- a/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties +++ b/nifi-registry-resources/src/main/resources/conf/nifi-registry.properties @@ -32,3 +32,6 @@ nifi.registry.security.truststoreType=${nifi.registry.security.truststoreType} nifi.registry.security.truststorePasswd=${nifi.registry.security.truststorePasswd} nifi.registry.security.needClientAuth=${nifi.registry.security.needClientAuth} nifi.registry.security.authorized.users=${nifi.registry.security.authorized.users} + +# providers properties # +nifi.registry.providers.configuration.file=${nifi.registry.providers.configuration.file} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-resources/src/main/resources/conf/providers.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-resources/src/main/resources/conf/providers.xml b/nifi-registry-resources/src/main/resources/conf/providers.xml new file mode 100644 index 0000000..450eecb --- /dev/null +++ b/nifi-registry-resources/src/main/resources/conf/providers.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + 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. +--> +<providers> + + <metadataProvider> + <class>org.apache.nifi.registry.metadata.FileSystemMetadataProvider</class> + <property name="Metadata File">./metadata.xml</property> + </metadataProvider> + + <flowPersistenceProvider> + <class>org.apache.nifi.registry.flow.FileSystemFlowPersistenceProvider</class> + <property name="Flow Storage Directory">./flow_storage</property> + </flowPersistenceProvider> + +</providers> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-service-api/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-service-api/pom.xml b/nifi-registry-service-api/pom.xml deleted file mode 100644 index dc0e8bd..0000000 --- a/nifi-registry-service-api/pom.xml +++ /dev/null @@ -1,35 +0,0 @@ -<?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"> - <parent> - <groupId>org.apache.nifi.registry</groupId> - <artifactId>nifi-registry</artifactId> - <version>0.0.1-SNAPSHOT</version> - </parent> - <modelVersion>4.0.0</modelVersion> - <artifactId>nifi-registry-service-api</artifactId> - <packaging>jar</packaging> - - <dependencies> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.12</version> - <scope>test</scope> - </dependency> - </dependencies> -</project> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/StringUtils.java ---------------------------------------------------------------------- diff --git a/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/StringUtils.java b/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/StringUtils.java new file mode 100644 index 0000000..43ab825 --- /dev/null +++ b/nifi-registry-utils/src/main/java/org/apache/nifi/registry/util/StringUtils.java @@ -0,0 +1,99 @@ +/* + * 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.registry.util; + +import java.util.Collection; + +public class StringUtils { + + public static final String EMPTY = ""; + + public static boolean isBlank(final String str) { + if (str == null || str.isEmpty()) { + return true; + } + for (int i = 0; i < str.length(); i++) { + if (!Character.isWhitespace(str.charAt(i))) { + return false; + } + } + return true; + } + + public static boolean isEmpty(final String str) { + return str == null || str.isEmpty(); + } + + public static boolean startsWith(final String str, final String prefix) { + if (str == null || prefix == null) { + return (str == null && prefix == null); + } + if (prefix.length() > str.length()) { + return false; + } + return str.regionMatches(false, 0, prefix, 0, prefix.length()); + } + + public static String substringAfter(final String str, final String separator) { + if (isEmpty(str)) { + return str; + } + if (separator == null) { + return EMPTY; + } + int pos = str.indexOf(separator); + if (pos == -1) { + return EMPTY; + } + return str.substring(pos + separator.length()); + } + + public static String join(final Collection collection, String delimiter) { + if (collection == null || collection.size() == 0) { + return EMPTY; + } + final StringBuilder sb = new StringBuilder(collection.size() * 16); + for (Object element : collection) { + sb.append((String) element); + sb.append(delimiter); + } + return sb.toString().substring(0, sb.lastIndexOf(delimiter)); + } + + public static String padLeft(final String source, int length, char padding) { + if (source != null) { + StringBuilder sb = new StringBuilder(source).reverse(); + while (sb.length() < length) { + sb.append(padding); + } + return sb.reverse().toString(); + } + return null; + } + + public static String padRight(final String source, int length, char padding) { + if (source != null) { + StringBuilder sb = new StringBuilder(source); + while (sb.length() < length) { + sb.append(padding); + } + return sb.toString(); + } + return null; + } + +} http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-web-api/pom.xml ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/pom.xml b/nifi-registry-web-api/pom.xml index b8925f5..d799c23 100644 --- a/nifi-registry-web-api/pom.xml +++ b/nifi-registry-web-api/pom.xml @@ -91,7 +91,12 @@ </dependency> <dependency> <groupId>org.apache.nifi.registry</groupId> - <artifactId>nifi-registry-service-api</artifactId> + <artifactId>nifi-registry-framework</artifactId> + <version>0.0.1-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.apache.nifi.registry</groupId> + <artifactId>nifi-registry-provider-impl</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java index f8295f3..e2fabdc 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/NiFiRegistryResourceConfig.java @@ -16,6 +16,11 @@ */ package org.apache.nifi.registry.web; +import org.apache.nifi.registry.flow.FlowPersistenceProvider; +import org.apache.nifi.registry.metadata.MetadataProvider; +import org.apache.nifi.registry.properties.NiFiRegistryProperties; +import org.apache.nifi.registry.provider.ProviderFactory; +import org.apache.nifi.registry.provider.StandardProviderFactory; import org.apache.nifi.registry.web.api.TestResource; import org.apache.nifi.registry.web.mapper.IllegalArgumentExceptionMapper; import org.apache.nifi.registry.web.mapper.ThrowableMapper; @@ -32,6 +37,12 @@ public class NiFiRegistryResourceConfig extends ResourceConfig { private static final Logger logger = LoggerFactory.getLogger(NiFiRegistryResourceConfig.class); public NiFiRegistryResourceConfig(@Context ServletContext servletContext) { + final NiFiRegistryProperties properties = (NiFiRegistryProperties) servletContext.getAttribute("nifi-registry.properties"); + + final ProviderFactory providerFactory = new StandardProviderFactory(properties); + final MetadataProvider metadataProvider = providerFactory.getMetadataProvider(); + final FlowPersistenceProvider flowPersistenceProvider = providerFactory.getFlowPersistenceProvider(); + register(HttpMethodOverrideFilter.class); // register the exception mappers @@ -39,6 +50,6 @@ public class NiFiRegistryResourceConfig extends ResourceConfig { register(new ThrowableMapper()); // register endpoints - register(new TestResource()); + register(new TestResource(metadataProvider, flowPersistenceProvider)); } } http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TestResource.java ---------------------------------------------------------------------- diff --git a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TestResource.java b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TestResource.java index 2564c8a..cc6d846 100644 --- a/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TestResource.java +++ b/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/TestResource.java @@ -16,6 +16,8 @@ */ package org.apache.nifi.registry.web.api; +import org.apache.nifi.registry.flow.FlowPersistenceProvider; +import org.apache.nifi.registry.metadata.MetadataProvider; import org.apache.nifi.registry.web.response.TestEntity; import javax.ws.rs.GET; @@ -27,6 +29,23 @@ import javax.ws.rs.core.Response; @Path("/test") public class TestResource { + private final MetadataProvider metadataProvider; + + private final FlowPersistenceProvider flowPersistenceProvider; + + public TestResource(final MetadataProvider metadataProvider, final FlowPersistenceProvider flowPersistenceProvider) { + this.metadataProvider = metadataProvider; + this.flowPersistenceProvider = flowPersistenceProvider; + + if (this.metadataProvider == null) { + throw new IllegalStateException("MetadataProvider cannot be null"); + } + + if (this.flowPersistenceProvider == null) { + throw new IllegalStateException("FlowPersistenceProvider cannot be null"); + } + } + @GET @Produces(MediaType.APPLICATION_JSON) public Response getTest() { http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/9eb0cef0/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 4185344..6538337 100644 --- a/pom.xml +++ b/pom.xml @@ -30,16 +30,18 @@ <modules> <module>nifi-registry-properties</module> <module>nifi-registry-utils</module> - <module>nifi-registry-flow-data-model</module> + <module>nifi-registry-data-model</module> <module>nifi-registry-jetty</module> <module>nifi-registry-resources</module> <module>nifi-registry-runtime</module> <module>nifi-registry-security</module> - <module>nifi-registry-service-api</module> + <module>nifi-registry-framework</module> + <module>nifi-registry-provider-api</module> + <module>nifi-registry-provider-impl</module> <module>nifi-registry-web-api</module> <module>nifi-registry-web-ui</module> <module>nifi-registry-bootstrap</module> - <module>nifi-registry-assembly</module> + <module>nifi-registry-assembly</module> </modules> <url>https://nifi.apache.org/registry.html</url> <organization> @@ -246,6 +248,11 @@ <artifactId>commons-lang3</artifactId> <version>3.5</version> </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>2.5</version> + </dependency> </dependencies> </dependencyManagement>
