You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jp...@apache.org on 2016/04/19 23:00:16 UTC
nifi-minifi git commit: MINIFI-12 initial commit of http config
change notifier
Repository: nifi-minifi
Updated Branches:
refs/heads/master 11f220d8d -> a1d2fd3fe
MINIFI-12 initial commit of http config change notifier
This closes #13
Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi/commit/a1d2fd3f
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi/tree/a1d2fd3f
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi/diff/a1d2fd3f
Branch: refs/heads/master
Commit: a1d2fd3fe6b0b2cdd50394e2451aa10d5c9c81e9
Parents: 11f220d
Author: Joseph Percivall <jo...@yahoo.com>
Authored: Thu Apr 14 19:01:54 2016 -0400
Committer: Joseph Percivall <jo...@yahoo.com>
Committed: Tue Apr 19 16:59:43 2016 -0400
----------------------------------------------------------------------
.travis.yml | 2 -
minifi-assembly/NOTICE | 7 +-
minifi-bootstrap/pom.xml | 20 ++
.../configuration/RestChangeNotifier.java | 259 +++++++++++++++++++
.../configuration/TestRestChangeNotifier.java | 51 ++++
.../TestRestChangeNotifierSSL.java | 96 +++++++
.../configuration/util/MockChangeListener.java | 46 ++++
.../util/TestRestChangeNotifierCommon.java | 89 +++++++
.../src/test/resources/localhost-ks.jks | Bin 0 -> 3512 bytes
.../src/test/resources/localhost-ts.jks | Bin 0 -> 1816 bytes
.../src/test/resources/testUploadFile.txt | 18 ++
.../src/main/resources/conf/bootstrap.conf | 6 +
pom.xml | 28 +-
13 files changed, 616 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index b5c02d0..811a4c2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,8 +5,6 @@ os:
jdk:
- oraclejdk8
- - oraclejdk7
- - openjdk7
# before_install aids in a couple workarounds for issues within the Travis-CI environment
# 1. Workaround for buffer overflow issues with OpenJDK versions of java as per https://github.com/travis-ci/travis-ci/issues/5227#issuecomment-165135711
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-assembly/NOTICE
----------------------------------------------------------------------
diff --git a/minifi-assembly/NOTICE b/minifi-assembly/NOTICE
index 90163f2..e7f6169 100644
--- a/minifi-assembly/NOTICE
+++ b/minifi-assembly/NOTICE
@@ -13,4 +13,9 @@ The following binary components are provided under the Apache Software License v
(ASLv2) Apache NiFi
The following NOTICE information applies:
Apache NiFi
- Copyright 2014-2016 The Apache Software Foundation
\ No newline at end of file
+ Copyright 2014-2016 The Apache Software Foundation
+
+ (ASLv2) Jetty
+ The following NOTICE information applies:
+ Jetty Web Container
+ Copyright 1995-2015 Mort Bay Consulting Pty Ltd.
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/pom.xml
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/pom.xml b/minifi-bootstrap/pom.xml
index 68bc60a..2616190 100644
--- a/minifi-bootstrap/pom.xml
+++ b/minifi-bootstrap/pom.xml
@@ -56,6 +56,26 @@ limitations under the License.
</dependency>
<dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-framework-core</artifactId>
<version>0.6.0</version>
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java
new file mode 100644
index 0000000..5807f89
--- /dev/null
+++ b/minifi-bootstrap/src/main/java/org/apache/nifi/minifi/bootstrap/configuration/RestChangeNotifier.java
@@ -0,0 +1,259 @@
+/*
+ * 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.minifi.bootstrap.configuration;
+
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.HandlerCollection;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.eclipse.jetty.util.thread.QueuedThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.Set;
+
+import static org.apache.nifi.minifi.bootstrap.RunMiNiFi.NOTIFIER_PROPERTY_PREFIX;
+
+
+public class RestChangeNotifier implements ConfigurationChangeNotifier {
+
+ private final Set<ConfigurationChangeListener> configurationChangeListeners = new HashSet<>();
+ private final static Logger logger = LoggerFactory.getLogger(RestChangeNotifier.class);
+ private String configFile = null;
+ private final Server jetty;
+ public static final String GET_TEXT = "This is a config change listener for an Apache NiFi - MiNiFi instance.\n" +
+ "Use this rest server to upload a conf.yml to configure the MiNiFi instance.\n" +
+ "Send a POST http request to '/' to upload the file.";
+ public static final String POST_TEXT ="Configuration received, notifying listeners.\n";
+ public static final String OTHER_TEXT ="This is not a support HTTP operation. Please use GET to get more information or POST to upload a new config.yml file.\n";
+
+
+ public static final String POST = "POST";
+ public static final String GET = "GET";
+
+ public static final String PORT_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.port";
+ public static final String HOST_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.host";
+ public static final String TRUSTSTORE_LOCATION_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.truststore.location";
+ public static final String TRUSTSTORE_PASSWORD_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.truststore.password";
+ public static final String TRUSTSTORE_TYPE_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.truststore.type";
+ public static final String KEYSTORE_LOCATION_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.keystore.location";
+ public static final String KEYSTORE_PASSWORD_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.keystore.password";
+ public static final String KEYSTORE_TYPE_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.keystore.type";
+ public static final String NEED_CLIENT_AUTH_KEY = NOTIFIER_PROPERTY_PREFIX + ".http.need.client.auth";
+
+ public RestChangeNotifier(){
+ QueuedThreadPool queuedThreadPool = new QueuedThreadPool();
+ queuedThreadPool.setDaemon(true);
+ jetty = new Server(queuedThreadPool);
+ }
+
+ @Override
+ public void initialize(Properties properties) {
+ logger.info("Initializing");
+
+ // create the secure connector if keystore location is specified
+ if (properties.getProperty(KEYSTORE_LOCATION_KEY) != null) {
+ createSecureConnector(properties);
+ } else {
+ // create the unsecure connector otherwise
+ createConnector(properties);
+ }
+
+ HandlerCollection handlerCollection = new HandlerCollection(true);
+ handlerCollection.addHandler(new JettyHandler());
+ jetty.setHandler(handlerCollection);
+ }
+
+
+ @Override
+ public Set<ConfigurationChangeListener> getChangeListeners() {
+ return configurationChangeListeners;
+ }
+
+ @Override
+ public boolean registerListener(ConfigurationChangeListener listener) {
+ return configurationChangeListeners.add(listener);
+ }
+
+ @Override
+ public void notifyListeners() {
+ if (configFile == null){
+ throw new IllegalStateException("Attempting to notify listeners when there is no new config file.");
+ }
+
+ for (final ConfigurationChangeListener listener : getChangeListeners()) {
+ try (final ByteArrayInputStream fis = new ByteArrayInputStream(configFile.getBytes());) {
+ listener.handleChange(fis);
+ } catch (IOException ex) {
+ throw new IllegalStateException("Unable to read the changed file " + configFile, ex);
+ }
+ }
+
+ configFile = null;
+ }
+
+ @Override
+ public void start(){
+ try {
+ jetty.start();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+
+ @Override
+ public void close() throws IOException {
+ logger.warn("Shutting down the jetty server");
+ try {
+ jetty.stop();
+ jetty.destroy();
+ } catch (Exception e) {
+ throw new IOException(e);
+ }
+ logger.warn("Done shutting down the jetty server");
+ }
+
+ public URI getURI(){
+ return jetty.getURI();
+ }
+
+ public int getPort(){
+ if (!jetty.isStarted()) {
+ throw new IllegalStateException("Jetty server not started");
+ }
+ return ((ServerConnector) jetty.getConnectors()[0]).getLocalPort();
+ }
+
+ public String getConfigString(){
+ return configFile;
+ }
+
+ private void setConfigFile(String configFile){
+ this.configFile = configFile;
+ }
+
+ private void createConnector(Properties properties) {
+ final ServerConnector http = new ServerConnector(jetty);
+
+ http.setPort(Integer.parseInt(properties.getProperty(PORT_KEY, "0")));
+ http.setHost(properties.getProperty(HOST_KEY, "localhost"));
+
+ // Severely taxed or distant environments may have significant delays when executing.
+ http.setIdleTimeout(30000L);
+ jetty.addConnector(http);
+
+ logger.info("Added an http connector on the host '{}' and port '{}'", new Object[]{http.getHost(), http.getPort()});
+ }
+
+ private void createSecureConnector(Properties properties) {
+ SslContextFactory ssl = new SslContextFactory();
+
+ if (properties.getProperty(KEYSTORE_LOCATION_KEY) != null) {
+ ssl.setKeyStorePath(properties.getProperty(KEYSTORE_LOCATION_KEY));
+ ssl.setKeyStorePassword(properties.getProperty(KEYSTORE_PASSWORD_KEY));
+ ssl.setKeyStoreType(properties.getProperty(KEYSTORE_TYPE_KEY));
+ }
+
+ if (properties.getProperty(TRUSTSTORE_LOCATION_KEY) != null) {
+ ssl.setTrustStorePath(properties.getProperty(TRUSTSTORE_LOCATION_KEY));
+ ssl.setTrustStorePassword(properties.getProperty(TRUSTSTORE_PASSWORD_KEY));
+ ssl.setTrustStoreType(properties.getProperty(TRUSTSTORE_TYPE_KEY));
+ ssl.setNeedClientAuth(Boolean.parseBoolean(properties.getProperty(NEED_CLIENT_AUTH_KEY, "true")));
+ }
+
+ // build the connector
+ final ServerConnector https = new ServerConnector(jetty, ssl);
+
+ // set host and port
+ https.setPort(Integer.parseInt(properties.getProperty(PORT_KEY,"0")));
+ https.setHost(properties.getProperty(HOST_KEY, "localhost"));
+
+ // Severely taxed environments may have significant delays when executing.
+ https.setIdleTimeout(30000L);
+
+ // add the connector
+ jetty.addConnector(https);
+
+ logger.info("Added an https connector on the host '{}' and port '{}'", new Object[]{https.getHost(), https.getPort()});
+ }
+
+
+ public class JettyHandler extends AbstractHandler {
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
+ throws IOException, ServletException {
+
+ logRequest(request);
+
+ baseRequest.setHandled(true);
+
+ if(POST.equals(request.getMethod())) {
+ final StringBuilder configBuilder = new StringBuilder();
+ BufferedReader reader = request.getReader();
+ if(reader != null && reader.ready()){
+ String line;
+ while ((line = reader.readLine()) != null) {
+ configBuilder.append(line);
+ configBuilder.append(System.getProperty("line.separator"));
+ }
+ }
+ setConfigFile(configBuilder.substring(0,configBuilder.length()-1));
+ notifyListeners();
+ writeOutput(response, POST_TEXT, 200);
+ } else if(GET.equals(request.getMethod())) {
+ writeOutput(response, GET_TEXT, 200);
+ } else {
+ writeOutput(response, OTHER_TEXT, 404);
+ }
+ }
+
+ private void writeOutput(HttpServletResponse response, String responseText, int responseCode) throws IOException {
+ response.setStatus(responseCode);
+ response.setContentType("text/plain");
+ response.setContentLength(responseText.length());
+ try (PrintWriter writer = response.getWriter()) {
+ writer.print(responseText);
+ writer.flush();
+ }
+ }
+
+ private void logRequest(HttpServletRequest request){
+ logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
+ logger.info("request method = " + request.getMethod());
+ logger.info("request url = " + request.getRequestURL());
+ logger.info("context path = " + request.getContextPath());
+ logger.info("request content type = " + request.getContentType());
+ logger.info("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java
new file mode 100644
index 0000000..75b44e3
--- /dev/null
+++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifier.java
@@ -0,0 +1,51 @@
+/*
+ * 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.minifi.bootstrap.configuration;
+
+
+import com.squareup.okhttp.OkHttpClient;
+import org.apache.nifi.minifi.bootstrap.configuration.util.TestRestChangeNotifierCommon;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import java.net.MalformedURLException;
+import java.util.Properties;
+
+
+public class TestRestChangeNotifier extends TestRestChangeNotifierCommon {
+
+ @BeforeClass
+ public static void setUp() throws InterruptedException, MalformedURLException {
+ Properties properties = new Properties();
+ restChangeNotifier = new RestChangeNotifier();
+ restChangeNotifier.initialize(properties);
+ restChangeNotifier.registerListener(mockChangeListener);
+ restChangeNotifier.start();
+
+ client = new OkHttpClient();
+
+ url = restChangeNotifier.getURI().toURL().toString();
+ Thread.sleep(1000);
+ }
+
+ @AfterClass
+ public static void stop() throws Exception {
+ restChangeNotifier.close();
+ client = null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java
new file mode 100644
index 0000000..908e693
--- /dev/null
+++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/TestRestChangeNotifierSSL.java
@@ -0,0 +1,96 @@
+/*
+ * 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.minifi.bootstrap.configuration;
+
+
+import com.squareup.okhttp.OkHttpClient;
+import org.apache.nifi.minifi.bootstrap.configuration.util.TestRestChangeNotifierCommon;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.util.Properties;
+
+
+public class TestRestChangeNotifierSSL extends TestRestChangeNotifierCommon {
+
+
+ @BeforeClass
+ public static void setUpHttps() throws CertificateException, NoSuchAlgorithmException, KeyStoreException, IOException, UnrecoverableKeyException, KeyManagementException, InterruptedException {
+ Properties properties = new Properties();
+ properties.setProperty(RestChangeNotifier.TRUSTSTORE_LOCATION_KEY, "./src/test/resources/localhost-ts.jks");
+ properties.setProperty(RestChangeNotifier.TRUSTSTORE_PASSWORD_KEY, "localtest");
+ properties.setProperty(RestChangeNotifier.TRUSTSTORE_TYPE_KEY, "JKS");
+ properties.setProperty(RestChangeNotifier.KEYSTORE_LOCATION_KEY, "./src/test/resources/localhost-ks.jks");
+ properties.setProperty(RestChangeNotifier.KEYSTORE_PASSWORD_KEY, "localtest");
+ properties.setProperty(RestChangeNotifier.KEYSTORE_TYPE_KEY, "JKS");
+ properties.setProperty(RestChangeNotifier.NEED_CLIENT_AUTH_KEY, "true");
+ restChangeNotifier = new RestChangeNotifier();
+ restChangeNotifier.initialize(properties);
+ restChangeNotifier.registerListener(mockChangeListener);
+ restChangeNotifier.start();
+
+ client = new OkHttpClient();
+
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+ TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(readKeyStore("./src/test/resources/localhost-ts.jks"));
+
+ KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(readKeyStore("./src/test/resources/localhost-ks.jks"), "localtest".toCharArray());
+
+ sslContext.init(keyManagerFactory.getKeyManagers(),trustManagerFactory.getTrustManagers(), new SecureRandom());
+ client.setSslSocketFactory(sslContext.getSocketFactory());
+
+ url = restChangeNotifier.getURI().toURL().toString();
+ Thread.sleep(1000);
+ }
+
+ @AfterClass
+ public static void stop() throws Exception {
+ restChangeNotifier.close();
+ client = null;
+ }
+
+ private static KeyStore readKeyStore(String path) throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+
+ char[] password = "localtest".toCharArray();
+
+ java.io.FileInputStream fis = null;
+ try {
+ fis = new java.io.FileInputStream(path);
+ ks.load(fis, password);
+ } finally {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ return ks;
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java
new file mode 100644
index 0000000..6843889
--- /dev/null
+++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/MockChangeListener.java
@@ -0,0 +1,46 @@
+/*
+ * 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.minifi.bootstrap.configuration.util;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.nifi.minifi.bootstrap.configuration.ConfigurationChangeListener;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class MockChangeListener implements ConfigurationChangeListener {
+ String confFile;
+
+ @Override
+ public void handleChange(InputStream inputStream) {
+ try {
+ confFile = IOUtils.toString(inputStream, "UTF-8");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public String getConfFile() {
+ return confFile;
+ }
+
+ public void setConfFile(String confFile) {
+ this.confFile = confFile;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java
new file mode 100644
index 0000000..b3c4f54
--- /dev/null
+++ b/minifi-bootstrap/src/test/java/org/apache/nifi/minifi/bootstrap/configuration/util/TestRestChangeNotifierCommon.java
@@ -0,0 +1,89 @@
+/*
+ * 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.minifi.bootstrap.configuration.util;
+
+import com.squareup.okhttp.Headers;
+import com.squareup.okhttp.MediaType;
+import com.squareup.okhttp.OkHttpClient;
+import com.squareup.okhttp.Request;
+import com.squareup.okhttp.RequestBody;
+import com.squareup.okhttp.Response;
+import org.apache.nifi.minifi.bootstrap.configuration.RestChangeNotifier;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public abstract class TestRestChangeNotifierCommon {
+
+ public static OkHttpClient client;
+ public static RestChangeNotifier restChangeNotifier;
+ public static final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("text/x-markdown; charset=utf-8");
+ public static String url;
+ public static MockChangeListener mockChangeListener = new MockChangeListener();
+
+ @Test
+ public void testGet() throws Exception {
+ assertEquals(1, restChangeNotifier.getChangeListeners().size());
+
+ Request request = new Request.Builder()
+ .url(url)
+ .build();
+
+ Response response = client.newCall(request).execute();
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ Headers responseHeaders = response.headers();
+ for (int i = 0; i < responseHeaders.size(); i++) {
+ System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
+ }
+
+ assertEquals(RestChangeNotifier.GET_TEXT, response.body().string());
+ }
+
+ @Test
+ public void testFileUpload() throws Exception {
+ assertEquals(1, restChangeNotifier.getChangeListeners().size());
+
+ File file = new File("src/test/resources/testUploadFile.txt");
+ assertTrue(file.exists());
+ assertTrue(file.canRead());
+
+ Request request = new Request.Builder()
+ .url(url)
+ .post(RequestBody.create(MEDIA_TYPE_MARKDOWN, file))
+ .addHeader("charset","UTF-8")
+ .build();
+
+ Response response = client.newCall(request).execute();
+ if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
+
+ Headers responseHeaders = response.headers();
+ for (int i = 0; i < responseHeaders.size(); i++) {
+ System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i));
+ }
+
+ assertEquals(RestChangeNotifier.POST_TEXT, response.body().string());
+
+ assertEquals(new String(Files.readAllBytes(file.toPath())), mockChangeListener.getConfFile());
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/resources/localhost-ks.jks
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/resources/localhost-ks.jks b/minifi-bootstrap/src/test/resources/localhost-ks.jks
new file mode 100755
index 0000000..df36197
Binary files /dev/null and b/minifi-bootstrap/src/test/resources/localhost-ks.jks differ
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/resources/localhost-ts.jks
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/resources/localhost-ts.jks b/minifi-bootstrap/src/test/resources/localhost-ts.jks
new file mode 100755
index 0000000..7824378
Binary files /dev/null and b/minifi-bootstrap/src/test/resources/localhost-ts.jks differ
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-bootstrap/src/test/resources/testUploadFile.txt
----------------------------------------------------------------------
diff --git a/minifi-bootstrap/src/test/resources/testUploadFile.txt b/minifi-bootstrap/src/test/resources/testUploadFile.txt
new file mode 100644
index 0000000..cbd1af8
--- /dev/null
+++ b/minifi-bootstrap/src/test/resources/testUploadFile.txt
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ */
+
+ this is a test upload file created to test the RestChangeListener
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf
----------------------------------------------------------------------
diff --git a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf b/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf
index c9626da..107d9cc 100644
--- a/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf
+++ b/minifi-nar-bundles/minifi-framework-bundle/minifi-framework/minifi-resources/src/main/resources/conf/bootstrap.conf
@@ -33,6 +33,7 @@ nifi.minifi.config=./conf/config.yml
# Notifiers to use for the associated agent, comma separated list of class names
#nifi.minifi.notifier.components=org.apache.nifi.minifi.bootstrap.configuration.FileChangeNotifier
+#nifi.minifi.notifier.components=org.apache.nifi.minifi.bootstrap.configuration.RestChangeNotifier
# File change notifier configuration
@@ -41,6 +42,11 @@ nifi.minifi.config=./conf/config.yml
# How frequently the file specified by 'nifi.minifi.notifier.file.config.path' should be evaluated for changes.
#nifi.minifi.notifier.file.polling.period.seconds=5
+# Rest change notifier configuration
+
+# Port on which the Jetty server will bind to, keep commented for a random open port
+#nifi.minifi.notifier.http.port=8338
+
# Disable JSR 199 so that we can use JSP's without running a JDK
java.arg.1=-Dorg.apache.jasper.compiler.disablejsr199=true
http://git-wip-us.apache.org/repos/asf/nifi-minifi/blob/a1d2fd3f/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index cdd8357..b765c7f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,14 +86,15 @@ limitations under the License.
<url>https://issues.apache.org/jira/browse/MINIFI</url>
</issueManagement>
<properties>
- <maven.compiler.source>1.7</maven.compiler.source>
- <maven.compiler.target>1.7</maven.compiler.target>
+ <maven.compiler.source>1.8</maven.compiler.source>
+ <maven.compiler.target>1.8</maven.compiler.target>
<maven.min-version>3.1.0</maven.min-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<inceptionYear>2016</inceptionYear>
<org.slf4j.version>1.7.12</org.slf4j.version>
<org.apache.nifi.version>0.6.0</org.apache.nifi.version>
+ <jetty.version>9.3.8.v20160314</jetty.version>
</properties>
<dependencies>
@@ -177,6 +178,16 @@ limitations under the License.
<version>${org.slf4j.version}</version>
<scope>provided</scope>
</dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <version>${jetty.version}</version>
+ </dependency>
<!-- NiFi Modules -->
<dependency>
@@ -368,7 +379,18 @@ limitations under the License.
<artifactId>slf4j-simple</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
-
+ <dependency>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>2.7.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>