You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jo...@apache.org on 2014/12/15 11:14:53 UTC

[08/12] incubator-nifi git commit: NIFI-169 well it finally all builds. There is a classpath issue still to sort out which impacts startup

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/java/org/apache/nifi/distributed/cache/server/set/SimpleSetCache.java
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/java/org/apache/nifi/distributed/cache/server/set/SimpleSetCache.java b/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/java/org/apache/nifi/distributed/cache/server/set/SimpleSetCache.java
deleted file mode 100644
index 77d6481..0000000
--- a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/java/org/apache/nifi/distributed/cache/server/set/SimpleSetCache.java
+++ /dev/null
@@ -1,117 +0,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.
- */
-package org.apache.nifi.distributed.cache.server.set;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.nifi.distributed.cache.server.EvictionPolicy;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class SimpleSetCache implements SetCache {
-    private static final Logger logger = LoggerFactory.getLogger(SimpleSetCache.class);
-    
-    private final Map<ByteBuffer, SetCacheRecord> cache = new HashMap<>();
-    private final SortedMap<SetCacheRecord, ByteBuffer> inverseCacheMap;
-    
-    private final String serviceIdentifier;
-    
-    private final int maxSize;
-    
-    public SimpleSetCache(final String serviceIdentifier, final int maxSize, final EvictionPolicy evictionPolicy) {
-        inverseCacheMap = new TreeMap<>(evictionPolicy.getComparator());
-        this.serviceIdentifier = serviceIdentifier;
-        this.maxSize = maxSize;
-    }
-    
-    private synchronized SetCacheRecord evict() {
-        if ( cache.size() < maxSize ) {
-            return null;
-        }
-        
-        final SetCacheRecord recordToEvict = inverseCacheMap.firstKey();
-        final ByteBuffer valueToEvict = inverseCacheMap.remove(recordToEvict);
-        cache.remove(valueToEvict);
-        
-        if ( logger.isDebugEnabled() ) {
-            logger.debug("Evicting value {} from cache", new String(valueToEvict.array(), StandardCharsets.UTF_8));
-        }
-        
-        return recordToEvict;
-    }
-    
-    @Override
-    public synchronized SetCacheResult addIfAbsent(final ByteBuffer value) {
-        final SetCacheRecord record = cache.get(value);
-        if ( record == null ) {
-            final SetCacheRecord evicted = evict();
-            final SetCacheRecord newRecord = new SetCacheRecord(value);
-            cache.put(value, newRecord);
-            inverseCacheMap.put(newRecord, value);
-            return new SetCacheResult(true, newRecord, evicted);
-        } else {
-            // We have to remove the record and add it again in order to cause the Map to stay sorted
-            inverseCacheMap.remove(record);
-            record.hit();
-            inverseCacheMap.put(record, value);
-            
-            return new SetCacheResult(false, record, null);
-        }
-    }
-    
-    @Override
-    public synchronized SetCacheResult contains(final ByteBuffer value) {
-        final SetCacheRecord record = cache.get(value);
-        if ( record == null ) {
-            return new SetCacheResult(false, null, null);
-        } else {
-            // We have to remove the record and add it again in order to cause the Map to stay sorted
-            inverseCacheMap.remove(record);
-            record.hit();
-            inverseCacheMap.put(record, value);
-            
-            return new SetCacheResult(true, record, null);
-        }
-    }
-    
-    @Override
-    public synchronized SetCacheResult remove(final ByteBuffer value) {
-        final SetCacheRecord record = cache.remove(value);
-        if ( record == null ) {
-            return new SetCacheResult(false, null, null);
-        } else {
-            inverseCacheMap.remove(record);
-            return new SetCacheResult(true, record, null);
-        }
-    }
-    
-    @Override
-    public String toString() {
-        return "SimpleSetCache[service id=" + serviceIdentifier + "]";
-    }
-    
-    @Override
-    public void shutdown() throws IOException {
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService b/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
deleted file mode 100644
index 0509c7c..0000000
--- a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/META-INF/services/org.apache.nifi.controller.ControllerService
+++ /dev/null
@@ -1,16 +0,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.
-org.apache.nifi.distributed.cache.server.DistributedSetCacheServer
-org.apache.nifi.distributed.cache.server.map.DistributedMapCacheServer
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/docs/org.apache.nifi.distributed.cache.server.map.DistributedMapCacheServer/index.html
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/docs/org.apache.nifi.distributed.cache.server.map.DistributedMapCacheServer/index.html b/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/docs/org.apache.nifi.distributed.cache.server.map.DistributedMapCacheServer/index.html
deleted file mode 100644
index dca3aa1..0000000
--- a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/main/resources/docs/org.apache.nifi.distributed.cache.server.map.DistributedMapCacheServer/index.html
+++ /dev/null
@@ -1,82 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<!--
-  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.
--->
-<head>
-<meta charset="utf-8" />
-<title>Distributed Map Cache Client Service</title>
-<link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
-</head>
-
-<body>
-	<h2>Description:</h2>
-
-	<p>A Controller Service that starts an embedded server and listens for connections from clients. The
-	server provides the ability to query the cache, add data to the cache, and remove data from the cache.</p>
-
-
-
-	<p>
-		<strong>Properties:</strong>
-	</p>
-	<p>In the list below, the names of required properties appear
-		in bold. Any other properties (not in bold) are considered optional.
-		If a property has a default value, it is indicated. If a property
-		supports the use of the NiFi Expression Language (or simply,
-		"expression language"), that is also indicated.</p>
-
-	<ul>
-		<li><strong>Port</strong>
-			<ul>
-				<li>The port to listen on for incoming connections</li>
-				<li>Default value: 4557</li>
-				<li>Supports expression language: false</li>
-			</ul></li>
-		<li>SSL Context Service
-			<ul>
-				<li>If specified, this service will be used to create an SSL Context that will be used to secure communications; if not specified, communications will not be secure</li>
-				<li>Default value: no default</li>
-				<li>Supports expression language: false</li>
-			</ul></li>
-		<li><strong>Maximum Cache Entries</strong>
-			<ul>
-				<li>The maximum number of cache entries that the cache can hold
-				<li>Default value: 10,000</li>
-				<li>Supports expression language: false</li>
-			</ul></li>
-		<li><strong>Eviction Strategy</strong>
-			<ul>
-				<li>Determines which strategy should be used to evict values from the cache to make room for new entries. Valid values: 
-					<code>Least Frequently Used</code>, <code>Least Recently Used</code>, and <code>First In, First Out</code>
-				<li>Default value: Least Frequently Used</li>
-				<li>Supports expression language: false</li>
-			</ul></li>
-		<li>Persistence Directory
-			<ul>
-				<li>If specified, the cache will be persisted in the given directory; if not specified, the cache will be in-memory only</li>
-				<li>Default value: no default (in-memory)</li>
-				<li>Supports expression language: true - JVM and System Properties Only</li>
-			</ul></li>
-	</ul>
-
-
-	<i>See Also:</i>
-	<ul>
-		<li><a href="../org.apache.nifi.distributed.cache.client.DistributedMapCacheClientService/index.html">Distributed Map Cache Client Service</a></li>
-		<li><a href="../org.apache.nifi.ssl.StandardSSLContextService/index.html">Standard SSL Context Service</a></li>
-	</ul>
-
-</body>
-</html>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/java/org/apache/nifi/distributed/cache/server/TestServerAndClient.java
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/java/org/apache/nifi/distributed/cache/server/TestServerAndClient.java b/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/java/org/apache/nifi/distributed/cache/server/TestServerAndClient.java
deleted file mode 100644
index b5f3fd6..0000000
--- a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/java/org/apache/nifi/distributed/cache/server/TestServerAndClient.java
+++ /dev/null
@@ -1,530 +0,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.
- */
-package org.apache.nifi.distributed.cache.server;
-
-import org.apache.nifi.distributed.cache.server.DistributedSetCacheServer;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.net.ConnectException;
-import java.nio.charset.StandardCharsets;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.nifi.components.PropertyDescriptor;
-import org.apache.nifi.distributed.cache.client.Deserializer;
-import org.apache.nifi.distributed.cache.client.DistributedMapCacheClientService;
-import org.apache.nifi.distributed.cache.client.DistributedSetCacheClientService;
-import org.apache.nifi.distributed.cache.client.Serializer;
-import org.apache.nifi.distributed.cache.client.exception.DeserializationException;
-import org.apache.nifi.distributed.cache.server.map.DistributedMapCacheServer;
-import org.apache.nifi.reporting.InitializationException;
-import org.apache.nifi.ssl.SSLContextService.ClientAuth;
-import org.apache.nifi.ssl.StandardSSLContextService;
-import org.apache.nifi.util.MockConfigurationContext;
-import org.apache.nifi.util.MockControllerServiceInitializationContext;
-
-import org.apache.commons.lang3.SerializationException;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class TestServerAndClient {
-
-    private static Logger LOGGER;
-
-    static {
-        System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "info");
-        System.setProperty("org.slf4j.simpleLogger.showDateTime", "true");
-        System.setProperty("org.slf4j.simpleLogger.log.nifi.distributed.cache.server.AbstractCacheServer", "debug");
-        System.setProperty("org.slf4j.simpleLogger.log.nifi.distributed.cache.client.DistributedMapCacheClientService", "debug");
-        System.setProperty("org.slf4j.simpleLogger.log.nifi.distributed.cache.server.TestServerAndClient", "debug");
-        System.setProperty("org.slf4j.simpleLogger.log.nifi.remote.io.socket.ssl.SSLSocketChannel", "trace");
-        LOGGER = LoggerFactory.getLogger(TestServerAndClient.class);
-    }
-
-    @Test
-    public void testNonPersistentSetServerAndClient() throws InitializationException, IOException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create server
-        final DistributedSetCacheServer server = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        final DistributedSetCacheClientService client = createClient();
-        final Serializer<String> serializer = new StringSerializer();
-        final boolean added = client.addIfAbsent("test", serializer);
-        assertTrue(added);
-
-        final boolean contains = client.contains("test", serializer);
-        assertTrue(contains);
-
-        final boolean addedAgain = client.addIfAbsent("test", serializer);
-        assertFalse(addedAgain);
-
-        final boolean removed = client.remove("test", serializer);
-        assertTrue(removed);
-
-        final boolean containedAfterRemove = client.contains("test", serializer);
-        assertFalse(containedAfterRemove);
-
-        server.shutdownServer();
-    }
-
-    @Test
-    public void testPersistentSetServerAndClient() throws InitializationException, IOException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create server
-        final DistributedSetCacheServer server = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final File dataFile = new File("target/cache-data");
-        deleteRecursively(dataFile);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        serverProperties.put(DistributedSetCacheServer.PERSISTENCE_PATH, dataFile.getAbsolutePath());
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        final DistributedSetCacheClientService client = createClient();
-        final Serializer<String> serializer = new StringSerializer();
-        final boolean added = client.addIfAbsent("test", serializer);
-        final boolean added2 = client.addIfAbsent("test2", serializer);
-        assertTrue(added);
-        assertTrue(added2);
-
-        final boolean contains = client.contains("test", serializer);
-        final boolean contains2 = client.contains("test2", serializer);
-        assertTrue(contains);
-        assertTrue(contains2);
-
-        final boolean addedAgain = client.addIfAbsent("test", serializer);
-        assertFalse(addedAgain);
-
-        final boolean removed = client.remove("test", serializer);
-        assertTrue(removed);
-
-        final boolean containedAfterRemove = client.contains("test", serializer);
-        assertFalse(containedAfterRemove);
-
-        server.shutdownServer();
-
-        final DistributedSetCacheServer newServer = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext newServerInitContext = new MockControllerServiceInitializationContext(newServer, "server2");
-        newServer.initialize(newServerInitContext);
-
-        final MockConfigurationContext newServerContext = new MockConfigurationContext(serverProperties,
-                newServerInitContext.getControllerServiceLookup());
-        newServer.startServer(newServerContext);
-
-        assertFalse(client.contains("test", serializer));
-        assertTrue(client.contains("test2", serializer));
-
-        newServer.shutdownServer();
-    }
-
-    @Test
-    public void testPersistentSetServerAndClientWithLFUEvictions() throws InitializationException, IOException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create server
-        final DistributedSetCacheServer server = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final File dataFile = new File("target/cache-data");
-        deleteRecursively(dataFile);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        serverProperties.put(DistributedSetCacheServer.PERSISTENCE_PATH, dataFile.getAbsolutePath());
-        serverProperties.put(DistributedSetCacheServer.MAX_CACHE_ENTRIES, "3");
-
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        final DistributedSetCacheClientService client = createClient();
-        final Serializer<String> serializer = new StringSerializer();
-        final boolean added = client.addIfAbsent("test", serializer);
-        waitABit();
-        final boolean added2 = client.addIfAbsent("test2", serializer);
-        waitABit();
-        final boolean added3 = client.addIfAbsent("test3", serializer);
-        waitABit();
-        assertTrue(added);
-        assertTrue(added2);
-        assertTrue(added3);
-
-        final boolean contains = client.contains("test", serializer);
-        final boolean contains2 = client.contains("test2", serializer);
-        assertTrue(contains);
-        assertTrue(contains2);
-
-        final boolean addedAgain = client.addIfAbsent("test", serializer);
-        assertFalse(addedAgain);
-
-        final boolean added4 = client.addIfAbsent("test4", serializer);
-        assertTrue(added4);
-
-        // ensure that added3 was evicted because it was used least frequently
-        assertFalse(client.contains("test3", serializer));
-
-        server.shutdownServer();
-
-        final DistributedSetCacheServer newServer = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext newServerInitContext = new MockControllerServiceInitializationContext(newServer, "server2");
-        newServer.initialize(newServerInitContext);
-
-        final MockConfigurationContext newServerContext = new MockConfigurationContext(serverProperties,
-                newServerInitContext.getControllerServiceLookup());
-        newServer.startServer(newServerContext);
-
-        assertTrue(client.contains("test", serializer));
-        assertTrue(client.contains("test2", serializer));
-        assertFalse(client.contains("test3", serializer));
-        assertTrue(client.contains("test4", serializer));
-
-        newServer.shutdownServer();
-    }
-
-    @Test
-    public void testPersistentSetServerAndClientWithFIFOEvictions() throws InitializationException, IOException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create server
-        final DistributedSetCacheServer server = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final File dataFile = new File("target/cache-data");
-        deleteRecursively(dataFile);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        serverProperties.put(DistributedSetCacheServer.PERSISTENCE_PATH, dataFile.getAbsolutePath());
-        serverProperties.put(DistributedSetCacheServer.MAX_CACHE_ENTRIES, "3");
-        serverProperties.put(DistributedSetCacheServer.EVICTION_POLICY, DistributedSetCacheServer.EVICTION_STRATEGY_FIFO);
-
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        final DistributedSetCacheClientService client = createClient();
-        final Serializer<String> serializer = new StringSerializer();
-
-        // add 3 entries to the cache. But, if we add too fast, we'll have the same millisecond
-        // for the entry time so we don't know which entry will be evicted. So we wait a few millis in between
-        final boolean added = client.addIfAbsent("test", serializer);
-        waitABit();
-        final boolean added2 = client.addIfAbsent("test2", serializer);
-        waitABit();
-        final boolean added3 = client.addIfAbsent("test3", serializer);
-        waitABit();
-
-        assertTrue(added);
-        assertTrue(added2);
-        assertTrue(added3);
-
-        final boolean contains = client.contains("test", serializer);
-        final boolean contains2 = client.contains("test2", serializer);
-        assertTrue(contains);
-        assertTrue(contains2);
-
-        final boolean addedAgain = client.addIfAbsent("test", serializer);
-        assertFalse(addedAgain);
-
-        final boolean added4 = client.addIfAbsent("test4", serializer);
-        assertTrue(added4);
-
-        // ensure that added3 was evicted because it was used least frequently
-        assertFalse(client.contains("test", serializer));
-        assertTrue(client.contains("test3", serializer));
-
-        server.shutdownServer();
-
-        final DistributedSetCacheServer newServer = new DistributedSetCacheServer();
-        MockControllerServiceInitializationContext newServerInitContext = new MockControllerServiceInitializationContext(newServer, "server2");
-        newServer.initialize(newServerInitContext);
-
-        final MockConfigurationContext newServerContext = new MockConfigurationContext(serverProperties,
-                newServerInitContext.getControllerServiceLookup());
-        newServer.startServer(newServerContext);
-
-        assertFalse(client.contains("test", serializer));
-        assertTrue(client.contains("test2", serializer));
-        assertTrue(client.contains("test3", serializer));
-        assertTrue(client.contains("test4", serializer));
-
-        newServer.shutdownServer();
-    }
-
-    @Test
-    public void testNonPersistentMapServerAndClient() throws InitializationException, IOException, InterruptedException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create server
-        final DistributedMapCacheServer server = new DistributedMapCacheServer();
-        MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        DistributedMapCacheClientService client = new DistributedMapCacheClientService();
-        MockControllerServiceInitializationContext clientInitContext = new MockControllerServiceInitializationContext(client, "client");
-        client.initialize(clientInitContext);
-
-        final Map<PropertyDescriptor, String> clientProperties = new HashMap<>();
-        clientProperties.put(DistributedMapCacheClientService.HOSTNAME, "localhost");
-        clientProperties.put(DistributedMapCacheClientService.COMMUNICATIONS_TIMEOUT, "360 secs");
-        MockConfigurationContext clientContext = new MockConfigurationContext(clientProperties, clientInitContext.getControllerServiceLookup());
-        client.cacheConfig(clientContext);
-        final Serializer<String> valueSerializer = new StringSerializer();
-        final Serializer<String> keySerializer = new StringSerializer();
-        final Deserializer<String> deserializer = new StringDeserializer();
-
-        final String original = client.getAndPutIfAbsent("testKey", "test", keySerializer, valueSerializer, deserializer);
-        assertEquals(null, original);
-        LOGGER.debug("end getAndPutIfAbsent");
-
-        final boolean contains = client.containsKey("testKey", keySerializer);
-        assertTrue(contains);
-        LOGGER.debug("end containsKey");
-
-        final boolean added = client.putIfAbsent("testKey", "test", keySerializer, valueSerializer);
-        assertFalse(added);
-        LOGGER.debug("end putIfAbsent");
-
-        final String originalAfterPut = client.getAndPutIfAbsent("testKey", "test", keySerializer, valueSerializer, deserializer);
-        assertEquals("test", originalAfterPut);
-        LOGGER.debug("end getAndPutIfAbsent");
-
-        final boolean removed = client.remove("testKey", keySerializer);
-        assertTrue(removed);
-        LOGGER.debug("end remove");
-
-        final boolean containedAfterRemove = client.containsKey("testKey", keySerializer);
-        assertFalse(containedAfterRemove);
-
-        client.putIfAbsent("testKey", "test", keySerializer, valueSerializer);
-        client.close();
-        try {
-            client.containsKey("testKey", keySerializer);
-            fail("Should be closed and not accessible");
-        } catch (Exception e) {
-
-        }
-        client = null;
-        clientInitContext = null;
-        clientContext = null;
-
-        DistributedMapCacheClientService client2 = new DistributedMapCacheClientService();
-
-        MockControllerServiceInitializationContext clientInitContext2 = new MockControllerServiceInitializationContext(client2, "client2");
-        client2.initialize(clientInitContext2);
-
-        MockConfigurationContext clientContext2 = new MockConfigurationContext(clientProperties,
-                clientInitContext2.getControllerServiceLookup());
-        client2.cacheConfig(clientContext2);
-        assertFalse(client2.putIfAbsent("testKey", "test", keySerializer, valueSerializer));
-        assertTrue(client2.containsKey("testKey", keySerializer));
-        server.shutdownServer();
-        Thread.sleep(1000);
-        try {
-            client2.containsKey("testKey", keySerializer);
-            fail("Should have blown exception!");
-        } catch (ConnectException e) {
-            client2 = null;
-            clientContext2 = null;
-            clientInitContext2 = null;
-        }
-        Thread.sleep(2000);
-        System.gc();
-        LOGGER.debug("end testNonPersistentMapServerAndClient");
-    }
-
-    @Test
-    public void testClientTermination() throws InitializationException, IOException, InterruptedException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create server
-        final DistributedMapCacheServer server = new DistributedMapCacheServer();
-        MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        DistributedMapCacheClientService client = new DistributedMapCacheClientService();
-        MockControllerServiceInitializationContext clientInitContext = new MockControllerServiceInitializationContext(client, "client");
-        client.initialize(clientInitContext);
-
-        final Map<PropertyDescriptor, String> clientProperties = new HashMap<>();
-        clientProperties.put(DistributedMapCacheClientService.HOSTNAME, "localhost");
-        clientProperties.put(DistributedMapCacheClientService.COMMUNICATIONS_TIMEOUT, "360 secs");
-        MockConfigurationContext clientContext = new MockConfigurationContext(clientProperties, clientInitContext.getControllerServiceLookup());
-        client.cacheConfig(clientContext);
-        final Serializer<String> valueSerializer = new StringSerializer();
-        final Serializer<String> keySerializer = new StringSerializer();
-        final Deserializer<String> deserializer = new StringDeserializer();
-
-        final String original = client.getAndPutIfAbsent("testKey", "test", keySerializer, valueSerializer, deserializer);
-        assertEquals(null, original);
-
-        final boolean contains = client.containsKey("testKey", keySerializer);
-        assertTrue(contains);
-
-        final boolean added = client.putIfAbsent("testKey", "test", keySerializer, valueSerializer);
-        assertFalse(added);
-
-        final String originalAfterPut = client.getAndPutIfAbsent("testKey", "test", keySerializer, valueSerializer, deserializer);
-        assertEquals("test", originalAfterPut);
-
-        final boolean removed = client.remove("testKey", keySerializer);
-        assertTrue(removed);
-
-        final boolean containedAfterRemove = client.containsKey("testKey", keySerializer);
-        assertFalse(containedAfterRemove);
-
-        client = null;
-        clientInitContext = null;
-        clientContext = null;
-        Thread.sleep(2000);
-        System.gc();
-        server.shutdownServer();
-    }
-
-    @Ignore
-    @Test
-    public void testSSLWith2RequestsWithServerTimeout() throws InitializationException, IOException, InterruptedException {
-        LOGGER.info("Testing " + Thread.currentThread().getStackTrace()[1].getMethodName());
-        // Create SSLContext Service
-        final StandardSSLContextService sslService = new StandardSSLContextService();
-        final MockControllerServiceInitializationContext sslServerInitContext = new MockControllerServiceInitializationContext(sslService,
-                "ssl-context");
-        sslService.initialize(sslServerInitContext);
-
-        final Map<PropertyDescriptor, String> sslServerProps = new HashMap<>();
-        sslServerProps.put(StandardSSLContextService.KEYSTORE, "src/test/resources/localhost-ks.jks");
-        sslServerProps.put(StandardSSLContextService.KEYSTORE_PASSWORD, "localtest");
-        sslServerProps.put(StandardSSLContextService.KEYSTORE_TYPE, "JKS");
-        sslServerProps.put(StandardSSLContextService.TRUSTSTORE, "src/test/resources/localhost-ts.jks");
-        sslServerProps.put(StandardSSLContextService.TRUSTSTORE_PASSWORD, "localtest");
-        sslServerProps.put(StandardSSLContextService.TRUSTSTORE_TYPE, "JKS");
-        MockConfigurationContext sslServerContext = new MockConfigurationContext(sslServerProps, sslServerInitContext);
-        sslService.onConfigured(sslServerContext);
-        sslService.createSSLContext(ClientAuth.REQUIRED);
-        // Create server
-        final DistributedMapCacheServer server = new DistributedMapCacheServer();
-        final MockControllerServiceInitializationContext serverInitContext = new MockControllerServiceInitializationContext(server, "server");
-        server.initialize(serverInitContext);
-
-        final Map<PropertyDescriptor, String> serverProperties = new HashMap<>();
-        serverProperties.put(DistributedMapCacheServer.SSL_CONTEXT_SERVICE, "ssl-context");
-        final MockConfigurationContext serverContext = new MockConfigurationContext(serverProperties, serverInitContext.getControllerServiceLookup());
-        server.startServer(serverContext);
-
-        DistributedMapCacheClientService client = new DistributedMapCacheClientService();
-        MockControllerServiceInitializationContext clientInitContext = new MockControllerServiceInitializationContext(client, "client");
-        client.initialize(clientInitContext);
-
-        final Map<PropertyDescriptor, String> clientProperties = new HashMap<>();
-        clientProperties.put(DistributedMapCacheClientService.HOSTNAME, "localhost");
-        clientProperties.put(DistributedMapCacheClientService.COMMUNICATIONS_TIMEOUT, "360 secs");
-        clientProperties.put(DistributedMapCacheClientService.SSL_CONTEXT_SERVICE, "ssl-context");
-        MockConfigurationContext clientContext = new MockConfigurationContext(clientProperties, clientInitContext.getControllerServiceLookup());
-        client.cacheConfig(clientContext);
-        final Serializer<String> valueSerializer = new StringSerializer();
-        final Serializer<String> keySerializer = new StringSerializer();
-        final Deserializer<String> deserializer = new StringDeserializer();
-
-        final String original = client.getAndPutIfAbsent("testKey", "test", keySerializer, valueSerializer, deserializer);
-        assertEquals(null, original);
-
-        Thread.sleep(30000);
-        try {
-            final boolean contains = client.containsKey("testKey", keySerializer);
-            assertTrue(contains);
-        } catch (IOException e) {
-            // this is due to the server timing out in the middle of this request
-            assertTrue(e.getMessage().contains("Channel is closed"));
-        }
-
-        server.shutdownServer();
-    }
-
-    private void waitABit() {
-        try {
-            Thread.sleep(10L);
-        } catch (final InterruptedException e) {
-        }
-    }
-
-    private DistributedSetCacheClientService createClient() throws InitializationException {
-        final DistributedSetCacheClientService client = new DistributedSetCacheClientService();
-        MockControllerServiceInitializationContext clientInitContext = new MockControllerServiceInitializationContext(client, "client");
-        client.initialize(clientInitContext);
-
-        final Map<PropertyDescriptor, String> clientProperties = new HashMap<>();
-        clientProperties.put(DistributedSetCacheClientService.HOSTNAME, "localhost");
-        final MockConfigurationContext clientContext = new MockConfigurationContext(clientProperties, clientInitContext.getControllerServiceLookup());
-        client.onConfigured(clientContext);
-
-        return client;
-    }
-
-    private static class StringSerializer implements Serializer<String> {
-        @Override
-        public void serialize(final String value, final OutputStream output) throws SerializationException, IOException {
-            output.write(value.getBytes(StandardCharsets.UTF_8));
-        }
-    }
-
-    private static class StringDeserializer implements Deserializer<String> {
-        @Override
-        public String deserialize(final byte[] input) throws DeserializationException, IOException {
-            return (input.length == 0) ? null : new String(input, StandardCharsets.UTF_8);
-        }
-    }
-
-    private static void deleteRecursively(final File dataFile) throws IOException {
-        if (dataFile == null || !dataFile.exists()) {
-            return;
-        }
-
-        final File[] children = dataFile.listFiles();
-        for (final File child : children) {
-            if (child.isDirectory()) {
-                deleteRecursively(child);
-            } else {
-                for (int i = 0; i < 100 && child.exists(); i++) {
-                    child.delete();
-                }
-
-                if (child.exists()) {
-                    throw new IOException("Could not delete " + dataFile.getAbsolutePath());
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ks.jks
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ks.jks b/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ks.jks
deleted file mode 100755
index 81be31d..0000000
Binary files a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ks.jks and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ts.jks
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ts.jks b/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ts.jks
deleted file mode 100755
index 820e1e1..0000000
Binary files a/nar-bundles/distributed-cache-services-bundle/distributed-cache-server/src/test/resources/localhost-ts.jks and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/distributed-cache-services-nar/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/distributed-cache-services-nar/pom.xml b/nar-bundles/distributed-cache-services-bundle/distributed-cache-services-nar/pom.xml
deleted file mode 100644
index 75cab34..0000000
--- a/nar-bundles/distributed-cache-services-bundle/distributed-cache-services-nar/pom.xml
+++ /dev/null
@@ -1,49 +0,0 @@
-<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">
-<!--
-  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.
--->
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>org.apache.nifi</groupId>
-		<artifactId>distributed-cache-services-bundle</artifactId>
-		<version>0.0.1-SNAPSHOT</version>
-	</parent>
-
-	<artifactId>distributed-cache-services-nar</artifactId>
-	<name>Distributed Cache Services NAR</name>
-	<packaging>nar</packaging>
-
-	<dependencies>
-		<dependency>
-			<groupId>org.apache.nifi</groupId>
-			<artifactId>standard-services-api-nar</artifactId>
-			<type>nar</type>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.nifi</groupId>
-			<artifactId>distributed-cache-client-service</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.nifi</groupId>
-			<artifactId>distributed-cache-protocol</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.nifi</groupId>
-			<artifactId>distributed-cache-server</artifactId>
-			<version>${project.version}</version>
-		</dependency>
-	</dependencies>
-</project>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/distributed-cache-services-bundle/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/distributed-cache-services-bundle/pom.xml b/nar-bundles/distributed-cache-services-bundle/pom.xml
deleted file mode 100644
index dcfa541..0000000
--- a/nar-bundles/distributed-cache-services-bundle/pom.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<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">
-    <!--
-      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.
-    -->
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.apache.nifi</groupId>
-        <artifactId>standard-services-api-bundle</artifactId>
-        <version>0.0.1-SNAPSHOT</version>
-    </parent>
-
-    <artifactId>distributed-cache-services-bundle</artifactId>
-    <version>0.0.1-SNAPSHOT</version>
-    <name>Distributed Cache Services Bundle</name>
-    <packaging>pom</packaging>
-
-    <modules>
-        <module>distributed-cache-protocol</module>
-        <module>distributed-cache-client-service</module>
-        <module>distributed-cache-server</module>
-        <module>distributed-cache-services-nar</module>
-    </modules>
-
-
-    <dependencyManagement>
-        <dependencies>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>distributed-cache-client-service-api</artifactId>
-                <version>${standard.services.api.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>ssl-context-service-api</artifactId>
-                <version>${standard.services.api.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>nifi-processor-utils</artifactId>
-                <version>0.0.1-SNAPSHOT</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>nifi-stream-utils</artifactId>
-                <version>0.0.1-SNAPSHOT</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>remote-communications-utils</artifactId>
-                <version>0.0.1-SNAPSHOT</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>nifi-mock</artifactId>
-                <version>0.0.1-SNAPSHOT</version>
-                <scope>test</scope>
-            </dependency>
-            <dependency>
-                <groupId>wali</groupId>
-                <artifactId>wali</artifactId>
-                <version>3.0.0-SNAPSHOT</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.nifi</groupId>
-                <artifactId>ssl-context-service</artifactId>
-                <version>0.0.1-SNAPSHOT</version>
-                <scope>test</scope>
-            </dependency>
-        </dependencies>
-    </dependencyManagement>
-</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/cluster/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/cluster/pom.xml b/nar-bundles/framework-bundle/framework/cluster/pom.xml
index ad5dda7..78f4527 100644
--- a/nar-bundles/framework-bundle/framework/cluster/pom.xml
+++ b/nar-bundles/framework-bundle/framework/cluster/pom.xml
@@ -80,7 +80,6 @@
         <dependency>
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-compress</artifactId>
-            <version>1.9</version>
         </dependency>
         
         <!-- third party dependencies -->

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/core/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/core/pom.xml b/nar-bundles/framework-bundle/framework/core/pom.xml
index 547c75d..1836d32 100644
--- a/nar-bundles/framework-bundle/framework/core/pom.xml
+++ b/nar-bundles/framework-bundle/framework/core/pom.xml
@@ -117,9 +117,8 @@
             <artifactId>data-provenance-utils</artifactId>
         </dependency>
         <dependency>
-            <groupId>wali</groupId>
+            <groupId>org.apache.nifi</groupId>
             <artifactId>wali</artifactId>
-            <version>3.0.0-SNAPSHOT</version>
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/file-authorization-provider/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/file-authorization-provider/pom.xml b/nar-bundles/framework-bundle/framework/file-authorization-provider/pom.xml
new file mode 100644
index 0000000..cb01488
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/file-authorization-provider/pom.xml
@@ -0,0 +1,81 @@
+<?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-framework-parent</artifactId>
+        <version>0.0.1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>file-authorization-provider</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+    <name>Authorization Provider: File</name>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>src/main/resources</directory>
+            </resource>
+            <resource>
+                <directory>src/main/xsd</directory>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>jaxb2-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>xjc</id>
+                        <goals>
+                            <goal>xjc</goal>
+                        </goals>
+                        <configuration>
+                            <packageName>org.apache.nifi.user.generated</packageName>
+                        </configuration>
+                    </execution>
+                </executions>
+                <configuration>
+                    <generateDirectory>${project.build.directory}/generated-sources/jaxb</generateDirectory>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-file-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-properties</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
new file mode 100644
index 0000000..0f4a75c
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/java/org/apache/nifi/authorization/FileAuthorizationProvider.java
@@ -0,0 +1,568 @@
+/*
+ * 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.authorization;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import org.apache.nifi.authorization.annotation.AuthorityProviderContext;
+import org.apache.nifi.authorization.exception.AuthorityAccessException;
+import org.apache.nifi.authorization.exception.IdentityAlreadyExistsException;
+import org.apache.nifi.authorization.exception.ProviderCreationException;
+import org.apache.nifi.authorization.exception.UnknownIdentityException;
+import org.apache.nifi.file.FileUtils;
+import org.apache.nifi.user.generated.ObjectFactory;
+import org.apache.nifi.user.generated.Role;
+import org.apache.nifi.user.generated.User;
+import org.apache.nifi.user.generated.Users;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+/**
+ * Provides identity checks and grants authorities.
+ */
+public class FileAuthorizationProvider implements AuthorityProvider {
+
+    private static final Logger logger = LoggerFactory.getLogger(FileAuthorizationProvider.class);
+    private static final String USERS_XSD = "/users.xsd";
+    private static final String JAXB_GENERATED_PATH = "org.apache.nifi.user.generated";
+    private static final JAXBContext JAXB_CONTEXT = initializeJaxbContext();
+
+    /**
+     * Load the JAXBContext.
+     */
+    private static JAXBContext initializeJaxbContext() {
+        try {
+            return JAXBContext.newInstance(JAXB_GENERATED_PATH, FileAuthorizationProvider.class.getClassLoader());
+        } catch (JAXBException e) {
+            throw new RuntimeException("Unable to create JAXBContext.");
+        }
+    }
+
+    private NiFiProperties properties;
+    private File usersFile;
+    private File restoreUsersFile;
+    private Users users;
+    private final Set<String> defaultAuthorities = new HashSet<>();
+
+    @Override
+    public void initialize(final AuthorityProviderInitializationContext initializationContext) throws ProviderCreationException {
+    }
+
+    @Override
+    public void onConfigured(final AuthorityProviderConfigurationContext configurationContext) throws ProviderCreationException {
+        try {
+            final String usersFilePath = configurationContext.getProperty("Authorized Users File");
+            if (usersFilePath == null || usersFilePath.trim().isEmpty()) {
+                throw new ProviderCreationException("The authorized users file must be specified.");
+            }
+
+            // the users file instance will never be null because a default is used
+            usersFile = new File(usersFilePath);
+            final File usersFileDirectory = usersFile.getParentFile();
+
+            // the restore directory is optional and may be null
+            final File restoreDirectory = properties.getRestoreDirectory();
+
+            if (restoreDirectory != null) {
+
+                // sanity check that restore directory is a directory, creating it if necessary
+                FileUtils.ensureDirectoryExistAndCanAccess(restoreDirectory);
+
+                // check that restore directory is not the same as the primary directory
+                if (usersFileDirectory.getAbsolutePath().equals(restoreDirectory.getAbsolutePath())) {
+                    throw new ProviderCreationException(String.format("Authorized User's directory '%s' is the same as restore directory '%s' ",
+                            usersFileDirectory.getAbsolutePath(), restoreDirectory.getAbsolutePath()));
+                }
+
+                // the restore copy will have same file name, but reside in a different directory
+                restoreUsersFile = new File(restoreDirectory, usersFile.getName());
+
+                // sync the primary copy with the restore copy
+                try {
+                    FileUtils.syncWithRestore(usersFile, restoreUsersFile, logger);
+                } catch (final IOException | IllegalStateException ioe) {
+                    throw new ProviderCreationException(ioe);
+                }
+
+            }
+
+            // load the users from the specified file
+            if (usersFile.exists()) {
+                // find the schema
+                final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+                final Schema schema = schemaFactory.newSchema(FileAuthorizationProvider.class.getResource(USERS_XSD));
+
+                // attempt to unmarshal
+                final Unmarshaller unmarshaller = JAXB_CONTEXT.createUnmarshaller();
+                unmarshaller.setSchema(schema);
+                final JAXBElement<Users> element = unmarshaller.unmarshal(new StreamSource(usersFile), Users.class);
+                users = element.getValue();
+            } else {
+                final ObjectFactory objFactory = new ObjectFactory();
+                users = objFactory.createUsers();
+            }
+
+            // attempt to load a default roles
+            final String rawDefaultAuthorities = configurationContext.getProperty("Default User Roles");
+            if (StringUtils.isNotBlank(rawDefaultAuthorities)) {
+                final Set<String> invalidDefaultAuthorities = new HashSet<>();
+
+                // validate the specified authorities
+                final String[] rawDefaultAuthorityList = rawDefaultAuthorities.split(",");
+                for (String rawAuthority : rawDefaultAuthorityList) {
+                    rawAuthority = rawAuthority.trim();
+                    final Authority authority = Authority.valueOfAuthority(rawAuthority);
+                    if (authority == null) {
+                        invalidDefaultAuthorities.add(rawAuthority);
+                    } else {
+                        defaultAuthorities.add(rawAuthority);
+                    }
+                }
+
+                // report any unrecognized authorities
+                if (!invalidDefaultAuthorities.isEmpty()) {
+                    logger.warn(String.format("The following default role(s) '%s' were not recognized. Possible values: %s.",
+                            StringUtils.join(invalidDefaultAuthorities, ", "), StringUtils.join(Authority.getRawAuthorities(), ", ")));
+                }
+            }
+        } catch (IOException | ProviderCreationException | SAXException | JAXBException e) {
+            throw new ProviderCreationException(e);
+        }
+
+    }
+
+    @Override
+    public void preDestruction() {
+    }
+
+    /**
+     * Determines if this provider has a default role.
+     *
+     * @return
+     */
+    private boolean hasDefaultRoles() {
+        return !defaultAuthorities.isEmpty();
+    }
+
+    /**
+     * Determines if the specified dn is known to this authority provider. When
+     * this provider is configured to have default role(s), all dn are
+     * considered to exist.
+     *
+     * @param dn
+     * @return True if he dn is known, false otherwise
+     */
+    @Override
+    public boolean doesDnExist(String dn) throws AuthorityAccessException {
+        if (hasDefaultRoles()) {
+            return true;
+        }
+
+        final User user = getUser(dn);
+        return user != null;
+    }
+
+    /**
+     * Loads the authorities for the specified user. If this provider is
+     * configured for default user role(s) and a non existent dn is specified, a
+     * new user will be automatically created with the default role(s).
+     *
+     * @param dn
+     * @return
+     * @throws UnknownIdentityException
+     * @throws AuthorityAccessException
+     */
+    @Override
+    public synchronized Set<Authority> getAuthorities(String dn) throws UnknownIdentityException, AuthorityAccessException {
+        final Set<Authority> authorities = EnumSet.noneOf(Authority.class);
+
+        // get the user 
+        final User user = getUser(dn);
+
+        // ensure the user was located
+        if (user == null) {
+            if (hasDefaultRoles()) {
+                logger.debug(String.format("User DN not found: %s. Creating new user with default roles.", dn));
+
+                // create the user (which will automatically add any default authorities)
+                addUser(dn, null);
+
+                // get the authorities for the newly created user
+                authorities.addAll(getAuthorities(dn));
+            } else {
+                throw new UnknownIdentityException(String.format("User DN not found: %s.", dn));
+            }
+        } else {
+            // create the authorities that this user has
+            for (final Role role : user.getRole()) {
+                authorities.add(Authority.valueOfAuthority(role.getName()));
+            }
+        }
+
+        return authorities;
+    }
+
+    /**
+     * Adds the specified authorities to the specified user. Regardless of
+     * whether this provider is configured for a default user role, when a non
+     * existent dn is specified, an UnknownIdentityException will be thrown.
+     *
+     * @param dn
+     * @param authorities
+     * @throws UnknownIdentityException
+     * @throws AuthorityAccessException
+     */
+    @Override
+    public synchronized void setAuthorities(String dn, Set<Authority> authorities) throws UnknownIdentityException, AuthorityAccessException {
+        // get the user
+        final User user = getUser(dn);
+
+        // ensure the user was located
+        if (user == null) {
+            throw new UnknownIdentityException(String.format("User DN not found: %s.", dn));
+        }
+
+        // add the user authorities
+        setUserAuthorities(user, authorities);
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Adds the specified authorities to the specified user.
+     *
+     * @param user
+     * @param authorities
+     */
+    private void setUserAuthorities(final User user, final Set<Authority> authorities) {
+        // clear the existing rules
+        user.getRole().clear();
+
+        // set the new roles
+        final ObjectFactory objFactory = new ObjectFactory();
+        for (final Authority authority : authorities) {
+            final Role role = objFactory.createRole();
+            role.setName(authority.toString());
+
+            // add the new role
+            user.getRole().add(role);
+        }
+    }
+
+    /**
+     * Adds the specified user. If this provider is configured with default
+     * role(s) they will be added to the new user.
+     *
+     * @param dn
+     * @param group
+     * @throws UnknownIdentityException
+     * @throws AuthorityAccessException
+     */
+    @Override
+    public synchronized void addUser(String dn, String group) throws IdentityAlreadyExistsException, AuthorityAccessException {
+        final User user = getUser(dn);
+
+        // ensure the user doesn't already exist
+        if (user != null) {
+            throw new IdentityAlreadyExistsException(String.format("User DN already exists: %s", dn));
+        }
+
+        // create the new user
+        final ObjectFactory objFactory = new ObjectFactory();
+        final User newUser = objFactory.createUser();
+
+        // set the user properties
+        newUser.setDn(dn);
+        newUser.setGroup(group);
+
+        // add default roles if appropriate
+        if (hasDefaultRoles()) {
+            for (final String authority : defaultAuthorities) {
+                Role role = objFactory.createRole();
+                role.setName(authority);
+
+                // add the role
+                newUser.getRole().add(role);
+            }
+        }
+
+        // add the user
+        users.getUser().add(newUser);
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Gets the users for the specified authority.
+     *
+     * @param authority
+     * @return
+     * @throws AuthorityAccessException
+     */
+    @Override
+    public synchronized Set<String> getUsers(Authority authority) throws AuthorityAccessException {
+        final Set<String> userSet = new HashSet<>();
+        for (final User user : users.getUser()) {
+            for (final Role role : user.getRole()) {
+                if (role.getName().equals(authority.toString())) {
+                    userSet.add(user.getDn());
+                }
+            }
+        }
+        return userSet;
+    }
+
+    /**
+     * Removes the specified user. Regardless of whether this provider is
+     * configured for a default user role, when a non existent dn is specified,
+     * an UnknownIdentityException will be thrown.
+     *
+     * @param dn
+     * @throws UnknownIdentityException
+     * @throws AuthorityAccessException
+     */
+    @Override
+    public synchronized void revokeUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+        // get the user
+        final User user = getUser(dn);
+
+        // ensure the user was located
+        if (user == null) {
+            throw new UnknownIdentityException(String.format("User DN not found: %s.", dn));
+        }
+
+        // remove the specified user
+        users.getUser().remove(user);
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void setUsersGroup(Set<String> dns, String group) throws UnknownIdentityException, AuthorityAccessException {
+        final Collection<User> groupedUsers = new HashSet<>();
+
+        // get the specified users
+        for (final String dn : dns) {
+            // get the user
+            final User user = getUser(dn);
+
+            // ensure the user was located
+            if (user == null) {
+                throw new UnknownIdentityException(String.format("User DN not found: %s.", dn));
+            }
+
+            groupedUsers.add(user);
+        }
+
+        // update each user group
+        for (final User user : groupedUsers) {
+            user.setGroup(group);
+        }
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void ungroupUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+        // get the user
+        final User user = getUser(dn);
+
+        // ensure the user was located
+        if (user == null) {
+            throw new UnknownIdentityException(String.format("User DN not found: %s.", dn));
+        }
+
+        // remove the users group
+        user.setGroup(null);
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public void ungroup(String group) throws AuthorityAccessException {
+        // get the user group
+        final Collection<User> userGroup = getUserGroup(group);
+
+        // ensure the user group was located
+        if (userGroup == null) {
+            return;
+        }
+
+        // update each user group
+        for (final User user : userGroup) {
+            user.setGroup(null);
+        }
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    @Override
+    public String getGroupForUser(String dn) throws UnknownIdentityException, AuthorityAccessException {
+        // get the user
+        final User user = getUser(dn);
+
+        // ensure the user was located
+        if (user == null) {
+            throw new UnknownIdentityException(String.format("User DN not found: %s.", dn));
+        }
+
+        return user.getGroup();
+    }
+
+    @Override
+    public void revokeGroup(String group) throws UnknownIdentityException, AuthorityAccessException {
+        // get the user group
+        final Collection<User> userGroup = getUserGroup(group);
+
+        // ensure the user group was located
+        if (userGroup == null) {
+            throw new UnknownIdentityException(String.format("User group not found: %s.", group));
+        }
+
+        // remove each user in the group
+        for (final User user : userGroup) {
+            users.getUser().remove(user);
+        }
+
+        try {
+            // save the file
+            save();
+        } catch (Exception e) {
+            throw new AuthorityAccessException(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * Locates the user with the specified DN.
+     *
+     * @param dn
+     * @return
+     */
+    private User getUser(String dn) throws UnknownIdentityException {
+        // ensure the DN was specified
+        if (dn == null) {
+            throw new UnknownIdentityException("User DN not specified.");
+        }
+
+        // attempt to get the user and ensure it was located
+        User desiredUser = null;
+        for (final User user : users.getUser()) {
+            if (dn.equalsIgnoreCase(user.getDn())) {
+                desiredUser = user;
+                break;
+            }
+        }
+
+        return desiredUser;
+    }
+
+    /**
+     * Locates all users that are part of the specified group.
+     *
+     * @param group
+     * @return
+     * @throws UnknownIdentityException
+     */
+    private Collection<User> getUserGroup(String group) throws UnknownIdentityException {
+        // ensure the DN was specified
+        if (group == null) {
+            throw new UnknownIdentityException("User group not specified.");
+        }
+
+        // get all users with this group
+        Collection<User> userGroup = null;
+        for (final User user : users.getUser()) {
+            if (group.equals(user.getGroup())) {
+                if (userGroup == null) {
+                    userGroup = new HashSet<>();
+                }
+                userGroup.add(user);
+            }
+        }
+
+        return userGroup;
+    }
+
+    /**
+     * Saves the users file.
+     *
+     * @throws Exception
+     */
+    private void save() throws Exception {
+        final Marshaller marshaller = JAXB_CONTEXT.createMarshaller();
+        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
+
+        // save users to restore directory before primary directory
+        if (restoreUsersFile != null) {
+            marshaller.marshal(users, restoreUsersFile);
+        }
+
+        // save users to primary directory
+        marshaller.marshal(users, usersFile);
+    }
+
+    @AuthorityProviderContext
+    public void setNiFiProperties(NiFiProperties properties) {
+        this.properties = properties;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/resources/META-INF/services/org.apache.nifi.authorization.AuthorityProvider
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/resources/META-INF/services/org.apache.nifi.authorization.AuthorityProvider b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/resources/META-INF/services/org.apache.nifi.authorization.AuthorityProvider
new file mode 100755
index 0000000..93d2941
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/resources/META-INF/services/org.apache.nifi.authorization.AuthorityProvider
@@ -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.
+org.apache.nifi.authorization.FileAuthorizationProvider

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/xsd/users.xsd
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/xsd/users.xsd b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/xsd/users.xsd
new file mode 100644
index 0000000..4ee1e17
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/main/xsd/users.xsd
@@ -0,0 +1,64 @@
+<?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">
+    <!-- role -->
+    <xs:complexType name="Role">
+        <xs:attribute name="name">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:enumeration value="ROLE_MONITOR"/>
+                    <xs:enumeration value="ROLE_PROVENANCE"/>
+                    <xs:enumeration value="ROLE_DFM"/>
+                    <xs:enumeration value="ROLE_ADMIN"/>
+                    <xs:enumeration value="ROLE_PROXY"/>
+                    <xs:enumeration value="ROLE_NIFI"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <!-- user -->
+    <xs:complexType name="User">
+        <xs:sequence>
+            <xs:element name="role" type="Role" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="dn">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+        <xs:attribute name="group">
+            <xs:simpleType>
+                <xs:restriction base="xs:string">
+                    <xs:minLength value="1"/>
+                    <xs:pattern value=".*[^\s].*"/>
+                </xs:restriction>
+            </xs:simpleType>
+        </xs:attribute>
+    </xs:complexType>
+
+    <!-- users -->
+    <xs:element name="users">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="user" type="User" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+        </xs:complexType>
+    </xs:element>
+</xs:schema>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/file-authorization-provider/src/test/java/org/apache/nifi/authorization/FileAuthorizationProviderTest.java
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/file-authorization-provider/src/test/java/org/apache/nifi/authorization/FileAuthorizationProviderTest.java b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/test/java/org/apache/nifi/authorization/FileAuthorizationProviderTest.java
new file mode 100644
index 0000000..3d0196d
--- /dev/null
+++ b/nar-bundles/framework-bundle/framework/file-authorization-provider/src/test/java/org/apache/nifi/authorization/FileAuthorizationProviderTest.java
@@ -0,0 +1,127 @@
+/*
+ * 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.authorization;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import org.apache.nifi.authorization.exception.ProviderCreationException;
+import org.apache.nifi.file.FileUtils;
+import org.apache.nifi.util.NiFiProperties;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+import org.junit.Ignore;
+import org.mockito.Mockito;
+
+@Ignore
+public class FileAuthorizationProviderTest {
+    
+    private FileAuthorizationProvider provider;
+    
+    private File primary;
+    
+    private File restore;
+    
+    private NiFiProperties mockProperties;
+    
+    private AuthorityProviderConfigurationContext mockConfigurationContext;
+    
+    @Before
+    public void setup() throws IOException {
+        
+        primary = new File("target/primary/users.txt");
+        restore = new File("target/restore/users.txt");
+        
+        System.out.println("absolute path: " + primary.getAbsolutePath());
+        
+        mockProperties = mock(NiFiProperties.class);
+        when(mockProperties.getRestoreDirectory()).thenReturn(restore.getParentFile());
+        
+        mockConfigurationContext = mock(AuthorityProviderConfigurationContext.class);
+        when(mockConfigurationContext.getProperty(Mockito.eq("Authorized Users File"))).thenReturn(primary.getPath());
+        
+        provider = new FileAuthorizationProvider();
+        provider.setNiFiProperties(mockProperties);
+        provider.initialize(null);
+    }     
+    
+    @After
+    public void cleanup() throws Exception {
+        deleteFile(primary);
+        deleteFile(restore);
+    }
+    
+    private boolean deleteFile(final File file) {
+        if(file.isDirectory()) {
+            FileUtils.deleteFilesInDir(file, null, null, true, true);
+        }
+        return FileUtils.deleteFile(file, null, 10);
+    }
+    
+    @Test
+    public void testPostContructionWhenRestoreDoesNotExist() throws Exception {
+        
+        byte[] primaryBytes = "<users/>".getBytes();
+        FileOutputStream fos = new FileOutputStream(primary);
+        fos.write(primaryBytes);
+        fos.close();
+        
+        provider.onConfigured(mockConfigurationContext);
+        assertEquals(primary.length(), restore.length());
+    }
+    
+    @Test
+    public void testPostContructionWhenPrimaryDoesNotExist() throws Exception {
+        
+        byte[] restoreBytes = "<users/>".getBytes();
+        FileOutputStream fos = new FileOutputStream(restore);
+        fos.write(restoreBytes);
+        fos.close();
+        
+        provider.onConfigured(mockConfigurationContext);
+        assertEquals(restore.length(), primary.length());
+        
+    }
+    
+    @Test(expected = ProviderCreationException.class)
+    public void testPostContructionWhenPrimaryDifferentThanRestore() throws Exception {
+        
+        byte[] primaryBytes = "<users></users>".getBytes();
+        FileOutputStream fos = new FileOutputStream(primary);
+        fos.write(primaryBytes);
+        fos.close();
+        
+        byte[] restoreBytes = "<users/>".getBytes();
+        fos = new FileOutputStream(restore);
+        fos.write(restoreBytes);
+        fos.close();
+        
+        provider.onConfigured(mockConfigurationContext);
+    }
+    
+    @Test
+    public void testPostContructionWhenPrimaryAndBackupDoNotExist() throws Exception {
+        
+        provider.onConfigured(mockConfigurationContext);
+        assertEquals(0, restore.length());
+        assertEquals(restore.length(), primary.length());
+    }
+    
+}

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/pom.xml b/nar-bundles/framework-bundle/framework/pom.xml
index 65fdaf1..f8ccdd0 100644
--- a/nar-bundles/framework-bundle/framework/pom.xml
+++ b/nar-bundles/framework-bundle/framework/pom.xml
@@ -35,6 +35,7 @@
         <module>cluster-protocol</module>
         <module>cluster-web</module>
         <module>cluster</module>
+        <module>file-authorization-provider</module>
         <module>cluster-authorization-provider</module>
         <module>user-actions</module>
         <module>administration</module>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/resources/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/resources/pom.xml b/nar-bundles/framework-bundle/framework/resources/pom.xml
index 9c984e7..ea25529 100644
--- a/nar-bundles/framework-bundle/framework/resources/pom.xml
+++ b/nar-bundles/framework-bundle/framework/resources/pom.xml
@@ -29,6 +29,9 @@
         <plugins>
             <plugin>
                 <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <attach>true</attach>
+                </configuration>
                 <executions>
                     <execution>
                         <id>make shared resource</id>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/runtime/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/runtime/pom.xml b/nar-bundles/framework-bundle/framework/runtime/pom.xml
index af4b404..e193729 100644
--- a/nar-bundles/framework-bundle/framework/runtime/pom.xml
+++ b/nar-bundles/framework-bundle/framework/runtime/pom.xml
@@ -29,6 +29,10 @@
             <artifactId>nifi-nar</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-properties</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>jul-to-slf4j</artifactId>
         </dependency>

http://git-wip-us.apache.org/repos/asf/incubator-nifi/blob/19d4a150/nar-bundles/framework-bundle/framework/site-to-site/pom.xml
----------------------------------------------------------------------
diff --git a/nar-bundles/framework-bundle/framework/site-to-site/pom.xml b/nar-bundles/framework-bundle/framework/site-to-site/pom.xml
index ce18ec7..30cd325 100644
--- a/nar-bundles/framework-bundle/framework/site-to-site/pom.xml
+++ b/nar-bundles/framework-bundle/framework/site-to-site/pom.xml
@@ -43,6 +43,10 @@
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-properties</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
             <artifactId>core-api</artifactId>
         </dependency>
         <dependency>
@@ -68,7 +72,6 @@
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
-            <version>4.3.6</version>
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
@@ -77,7 +80,6 @@
         <dependency>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
-            <version>1.10.8</version>
             <scope>test</scope>
         </dependency>
     </dependencies>