You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zeppelin.apache.org by zj...@apache.org on 2018/03/22 13:19:53 UTC
[4/7] zeppelin git commit: ZEPPELIN-3196. Plugin framework for
Zeppelin Engine
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java
new file mode 100644
index 0000000..9dd9fbf
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/java/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepo.java
@@ -0,0 +1,385 @@
+/*
+ * 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.zeppelin.notebook.repo.zeppelinhub;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.apache.zeppelin.notebook.Note;
+import org.apache.zeppelin.notebook.NoteInfo;
+import org.apache.zeppelin.notebook.repo.NotebookRepoWithVersionControl;
+import org.apache.zeppelin.notebook.repo.NotebookRepoSettingsInfo;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.model.Instance;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.model.UserTokenContainer;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.model.UserSessionContainer;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.rest.ZeppelinhubRestApiHandler;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.Client;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.utils.ZeppelinhubUtils;
+import org.apache.zeppelin.user.AuthenticationInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+/**
+ * ZeppelinHub repo class.
+ */
+public class ZeppelinHubRepo implements NotebookRepoWithVersionControl {
+ private static final Logger LOG = LoggerFactory.getLogger(ZeppelinHubRepo.class);
+ private static final String DEFAULT_SERVER = "https://www.zeppelinhub.com";
+ static final String ZEPPELIN_CONF_PROP_NAME_SERVER = "zeppelinhub.api.address";
+ static final String ZEPPELIN_CONF_PROP_NAME_TOKEN = "zeppelinhub.api.token";
+
+ private static final Gson GSON = new Gson();
+ private static final Note EMPTY_NOTE = new Note();
+ private Client websocketClient;
+ private UserTokenContainer tokenManager;
+
+ private String token;
+ private ZeppelinhubRestApiHandler restApiClient;
+
+ private ZeppelinConfiguration conf;
+
+ public ZeppelinHubRepo() {
+
+ }
+
+ public ZeppelinHubRepo(ZeppelinConfiguration conf) {
+ this();
+ init(conf);
+ }
+
+ public void init(ZeppelinConfiguration conf) {
+ this.conf = conf;
+ String zeppelinHubUrl = getZeppelinHubUrl(conf);
+ LOG.info("Initializing ZeppelinHub integration module");
+
+ token = conf.getString("ZEPPELINHUB_API_TOKEN", ZEPPELIN_CONF_PROP_NAME_TOKEN, "");
+ restApiClient = ZeppelinhubRestApiHandler.newInstance(zeppelinHubUrl);
+ //TODO(khalid): check which realm for authentication, pass to token manager
+ tokenManager = UserTokenContainer.init(restApiClient, token);
+
+ websocketClient = Client.initialize(getZeppelinWebsocketUri(conf),
+ getZeppelinhubWebsocketUri(conf), token, conf);
+ websocketClient.start();
+ }
+
+ private String getZeppelinHubWsUri(URI api) throws URISyntaxException {
+ URI apiRoot = api;
+ String scheme = apiRoot.getScheme();
+ int port = apiRoot.getPort();
+ if (port <= 0) {
+ port = (scheme != null && scheme.equals("https")) ? 443 : 80;
+ }
+
+ if (scheme == null) {
+ LOG.info("{} is not a valid zeppelinhub server address. proceed with default address {}",
+ apiRoot, DEFAULT_SERVER);
+ apiRoot = new URI(DEFAULT_SERVER);
+ scheme = apiRoot.getScheme();
+ port = apiRoot.getPort();
+ if (port <= 0) {
+ port = (scheme != null && scheme.equals("https")) ? 443 : 80;
+ }
+ }
+ String ws = scheme.equals("https") ? "wss://" : "ws://";
+ return ws + apiRoot.getHost() + ":" + port + "/async";
+ }
+
+ String getZeppelinhubWebsocketUri(ZeppelinConfiguration conf) {
+ String zeppelinHubUri = StringUtils.EMPTY;
+ try {
+ zeppelinHubUri = getZeppelinHubWsUri(new URI(conf.getString("ZEPPELINHUB_API_ADDRESS",
+ ZEPPELIN_CONF_PROP_NAME_SERVER, DEFAULT_SERVER)));
+ } catch (URISyntaxException e) {
+ LOG.error("Cannot get ZeppelinHub URI", e);
+ }
+ return zeppelinHubUri;
+ }
+
+ private String getZeppelinWebsocketUri(ZeppelinConfiguration conf) {
+ int port = conf.getServerPort();
+ if (port <= 0) {
+ port = 80;
+ }
+ String ws = conf.useSsl() ? "wss" : "ws";
+ return ws + "://localhost:" + port + "/ws";
+ }
+
+ // Used in tests
+ void setZeppelinhubRestApiHandler(ZeppelinhubRestApiHandler zeppelinhub) {
+ restApiClient = zeppelinhub;
+ }
+
+ String getZeppelinHubUrl(ZeppelinConfiguration conf) {
+ if (conf == null) {
+ LOG.error("Invalid configuration, cannot be null. Using default address {}", DEFAULT_SERVER);
+ return DEFAULT_SERVER;
+ }
+ URI apiRoot;
+ String zeppelinhubUrl;
+ try {
+ String url = conf.getString("ZEPPELINHUB_API_ADDRESS",
+ ZEPPELIN_CONF_PROP_NAME_SERVER,
+ DEFAULT_SERVER);
+ apiRoot = new URI(url);
+ } catch (URISyntaxException e) {
+ LOG.error("Invalid zeppelinhub url, using default address {}", DEFAULT_SERVER, e);
+ return DEFAULT_SERVER;
+ }
+
+ String scheme = apiRoot.getScheme();
+ if (scheme == null) {
+ LOG.info("{} is not a valid zeppelinhub server address. proceed with default address {}",
+ apiRoot, DEFAULT_SERVER);
+ zeppelinhubUrl = DEFAULT_SERVER;
+ } else {
+ zeppelinhubUrl = scheme + "://" + apiRoot.getHost();
+ if (apiRoot.getPort() > 0) {
+ zeppelinhubUrl += ":" + apiRoot.getPort();
+ }
+ }
+ return zeppelinhubUrl;
+ }
+
+ private boolean isSubjectValid(AuthenticationInfo subject) {
+ if (subject == null) {
+ return false;
+ }
+ return (subject.isAnonymous() && !conf.isAnonymousAllowed()) ? false : true;
+ }
+
+ @Override
+ public List<NoteInfo> list(AuthenticationInfo subject) throws IOException {
+ if (!isSubjectValid(subject)) {
+ return Collections.emptyList();
+ }
+ String token = getUserToken(subject.getUser());
+ String response = restApiClient.get(token, StringUtils.EMPTY);
+ List<NoteInfo> notes = GSON.fromJson(response, new TypeToken<List<NoteInfo>>() {}.getType());
+ if (notes == null) {
+ return Collections.emptyList();
+ }
+ LOG.info("ZeppelinHub REST API listing notes ");
+ return notes;
+ }
+
+ @Override
+ public Note get(String noteId, AuthenticationInfo subject) throws IOException {
+ if (StringUtils.isBlank(noteId) || !isSubjectValid(subject)) {
+ return EMPTY_NOTE;
+ }
+ String token = getUserToken(subject.getUser());
+ String response = restApiClient.get(token, noteId);
+ Note note = Note.fromJson(response);
+ if (note == null) {
+ return EMPTY_NOTE;
+ }
+ LOG.info("ZeppelinHub REST API get note {} ", noteId);
+ return note;
+ }
+
+ @Override
+ public void save(Note note, AuthenticationInfo subject) throws IOException {
+ if (note == null || !isSubjectValid(subject)) {
+ throw new IOException("Zeppelinhub failed to save note");
+ }
+ String jsonNote = note.toJson();
+ String token = getUserToken(subject.getUser());
+ LOG.info("ZeppelinHub REST API saving note {} ", note.getId());
+ restApiClient.put(token, jsonNote);
+ }
+
+ @Override
+ public void remove(String noteId, AuthenticationInfo subject) throws IOException {
+ if (StringUtils.isBlank(noteId) || !isSubjectValid(subject)) {
+ throw new IOException("Zeppelinhub failed to remove note");
+ }
+ String token = getUserToken(subject.getUser());
+ LOG.info("ZeppelinHub REST API removing note {} ", noteId);
+ restApiClient.del(token, noteId);
+ }
+
+ @Override
+ public void close() {
+ websocketClient.stop();
+ restApiClient.close();
+ }
+
+ @Override
+ public Revision checkpoint(String noteId, String checkpointMsg, AuthenticationInfo subject)
+ throws IOException {
+ if (StringUtils.isBlank(noteId) || !isSubjectValid(subject)) {
+ return Revision.EMPTY;
+ }
+ String endpoint = Joiner.on("/").join(noteId, "checkpoint");
+ String content = GSON.toJson(ImmutableMap.of("message", checkpointMsg));
+
+ String token = getUserToken(subject.getUser());
+ String response = restApiClient.putWithResponseBody(token, endpoint, content);
+
+ return GSON.fromJson(response, Revision.class);
+ }
+
+ @Override
+ public Note get(String noteId, String revId, AuthenticationInfo subject) throws IOException {
+ if (StringUtils.isBlank(noteId) || StringUtils.isBlank(revId) || !isSubjectValid(subject)) {
+ return EMPTY_NOTE;
+ }
+ String endpoint = Joiner.on("/").join(noteId, "checkpoint", revId);
+ String token = getUserToken(subject.getUser());
+ String response = restApiClient.get(token, endpoint);
+
+ Note note = Note.fromJson(response);
+ if (note == null) {
+ return EMPTY_NOTE;
+ }
+ LOG.info("ZeppelinHub REST API get note {} revision {}", noteId, revId);
+ return note;
+ }
+
+ @Override
+ public List<Revision> revisionHistory(String noteId, AuthenticationInfo subject) {
+ if (StringUtils.isBlank(noteId) || !isSubjectValid(subject)) {
+ return Collections.emptyList();
+ }
+ String endpoint = Joiner.on("/").join(noteId, "checkpoint");
+ List<Revision> history = Collections.emptyList();
+ try {
+ String token = getUserToken(subject.getUser());
+ String response = restApiClient.get(token, endpoint);
+ history = GSON.fromJson(response, new TypeToken<List<Revision>>(){}.getType());
+ } catch (IOException e) {
+ LOG.error("Cannot get note history", e);
+ }
+ return history;
+ }
+
+ private String getUserToken(String user) {
+ return tokenManager.getUserToken(user);
+ }
+
+ @Override
+ public List<NotebookRepoSettingsInfo> getSettings(AuthenticationInfo subject) {
+ if (!isSubjectValid(subject)) {
+ return Collections.emptyList();
+ }
+
+ List<NotebookRepoSettingsInfo> settings = Lists.newArrayList();
+ String user = subject.getUser();
+ String zeppelinHubUserSession = UserSessionContainer.instance.getSession(user);
+ String userToken = getUserToken(user);
+ List<Instance> instances;
+ List<Map<String, String>> values = Lists.newLinkedList();
+
+ try {
+ instances = tokenManager.getUserInstances(zeppelinHubUserSession);
+ } catch (IOException e) {
+ LOG.warn("Couldnt find instances for the session {}, returning empty collection",
+ zeppelinHubUserSession);
+ // user not logged
+ //TODO(xxx): handle this case.
+ instances = Collections.emptyList();
+ }
+
+ NotebookRepoSettingsInfo repoSetting = NotebookRepoSettingsInfo.newInstance();
+ repoSetting.type = NotebookRepoSettingsInfo.Type.DROPDOWN;
+ for (Instance instance : instances) {
+ if (instance.token.equals(userToken)) {
+ repoSetting.selected = Integer.toString(instance.id);
+ }
+ values.add(ImmutableMap.of("name", instance.name, "value", Integer.toString(instance.id)));
+ }
+
+ repoSetting.value = values;
+ repoSetting.name = "Instance";
+ settings.add(repoSetting);
+ return settings;
+ }
+
+ private void changeToken(int instanceId, String user) {
+ if (instanceId <= 0) {
+ LOG.error("User {} tried to switch to a non valid instance {}", user, instanceId);
+ return;
+ }
+
+ LOG.info("User {} will switch instance", user);
+ String ticket = UserSessionContainer.instance.getSession(user);
+ List<Instance> instances;
+ String currentToken = StringUtils.EMPTY, targetToken = StringUtils.EMPTY;
+ try {
+ instances = tokenManager.getUserInstances(ticket);
+ if (instances.isEmpty()) {
+ return;
+ }
+ currentToken = tokenManager.getExistingUserToken(user);
+ for (Instance instance : instances) {
+ if (instance.id == instanceId) {
+ LOG.info("User {} switched to instance {}", user, instance.name);
+ tokenManager.setUserToken(user, instance.token);
+ targetToken = instance.token;
+ break;
+ }
+ }
+ if (!StringUtils.isBlank(currentToken) && !StringUtils.isBlank(targetToken)) {
+ ZeppelinhubUtils.userSwitchTokenRoutine(user, currentToken, targetToken);
+ }
+ } catch (IOException e) {
+ LOG.error("Cannot switch instance for user {}", user, e);
+ }
+ }
+
+ @Override
+ public void updateSettings(Map<String, String> settings, AuthenticationInfo subject) {
+ if (!isSubjectValid(subject)) {
+ LOG.error("Invalid subject, cannot update Zeppelinhub settings");
+ return;
+ }
+ if (settings == null || settings.isEmpty()) {
+ LOG.error("Cannot update ZeppelinHub repo settings because of invalid settings");
+ return;
+ }
+
+ int instanceId = 0;
+ if (settings.containsKey("Instance")) {
+ try {
+ instanceId = Integer.parseInt(settings.get("Instance"));
+ } catch (NumberFormatException e) {
+ LOG.error("ZeppelinHub Instance Id in not a valid integer", e);
+ }
+ }
+ changeToken(instanceId, subject.getUser());
+ }
+
+ @Override
+ public Note setNoteRevision(String noteId, String revId, AuthenticationInfo subject)
+ throws IOException {
+ // Auto-generated method stub
+ return null;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/resources/META-INF/services/org.apache.zeppelin.notebook.repo.NotebookRepo
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/resources/META-INF/services/org.apache.zeppelin.notebook.repo.NotebookRepo b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/resources/META-INF/services/org.apache.zeppelin.notebook.repo.NotebookRepo
new file mode 100644
index 0000000..395d1cd
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/resources/META-INF/services/org.apache.zeppelin.notebook.repo.NotebookRepo
@@ -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.
+#
+
+org.apache.zeppelin.notebook.repo.zeppelinhub.ZeppelinHubRepo
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepoTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepoTest.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepoTest.java
new file mode 100644
index 0000000..2fa6d41
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/ZeppelinHubRepoTest.java
@@ -0,0 +1,155 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.commons.httpclient.HttpException;
+import org.apache.zeppelin.conf.ZeppelinConfiguration;
+import org.apache.zeppelin.notebook.Note;
+import org.apache.zeppelin.notebook.NoteInfo;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.rest.ZeppelinhubRestApiHandler;
+import org.apache.zeppelin.user.AuthenticationInfo;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.io.Files;
+
+
+public class ZeppelinHubRepoTest {
+ final String token = "AAA-BBB-CCC-00";
+ final String testAddr = "http://zeppelinhub.ltd";
+ final AuthenticationInfo auth = new AuthenticationInfo("anthony");
+
+ private ZeppelinHubRepo repo;
+ private File pathOfNotebooks = new File(System.getProperty("user.dir") + "/src/test/resources/list_of_notes");
+ private File pathOfNotebook = new File(System.getProperty("user.dir") + "/src/test/resources/note");
+
+ @Before
+ public void setUp() throws Exception {
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, testAddr);
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_TOKEN, token);
+
+ ZeppelinConfiguration conf = new ZeppelinConfiguration();
+ repo = new ZeppelinHubRepo();
+ repo.init(conf);
+ repo.setZeppelinhubRestApiHandler(getMockedZeppelinHandler());
+ }
+
+ private ZeppelinhubRestApiHandler getMockedZeppelinHandler() throws HttpException, IOException {
+ ZeppelinhubRestApiHandler mockedZeppelinhubHandler = mock(ZeppelinhubRestApiHandler.class);
+
+ byte[] listOfNotesResponse = Files.toByteArray(pathOfNotebooks);
+ when(mockedZeppelinhubHandler.get("AAA-BBB-CCC-00", ""))
+ .thenReturn(new String(listOfNotesResponse));
+
+ byte[] noteResponse = Files.toByteArray(pathOfNotebook);
+ when(mockedZeppelinhubHandler.get("AAA-BBB-CCC-00", "AAAAA"))
+ .thenReturn(new String(noteResponse));
+
+ return mockedZeppelinhubHandler;
+ }
+
+ @Test
+ public void testGetZeppelinhubUrl() {
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, testAddr);
+
+ ZeppelinConfiguration config = new ZeppelinConfiguration();
+ ZeppelinHubRepo repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinHubUrl(config)).isEqualTo("http://zeppelinhub.ltd");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "yolow");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinHubUrl(config)).isEqualTo("https://www.zeppelinhub.com");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "http://zeppelinhub.ltd:4242");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinHubUrl(config)).isEqualTo("http://zeppelinhub.ltd:4242");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "http://zeppelinhub.ltd:0");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinHubUrl(config)).isEqualTo("http://zeppelinhub.ltd");
+ }
+
+ @Test
+ public void testGetZeppelinHubWsEndpoint() {
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, testAddr);
+
+ ZeppelinConfiguration config = new ZeppelinConfiguration();
+ ZeppelinHubRepo repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("ws://zeppelinhub.ltd:80/async");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "https://zeppelinhub.ltd");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("wss://zeppelinhub.ltd:443/async");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "yolow");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("wss://www.zeppelinhub.com:443/async");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "http://zeppelinhub.ltd:4242");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("ws://zeppelinhub.ltd:4242/async");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "https://www.zeppelinhub.com");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("wss://www.zeppelinhub.com:443/async");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "http://www.zeppelinhub.com");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("ws://www.zeppelinhub.com:80/async");
+
+ System.setProperty(ZeppelinHubRepo.ZEPPELIN_CONF_PROP_NAME_SERVER, "https://www.zeppelinhub.com:4242");
+
+ config = new ZeppelinConfiguration();
+ repository = new ZeppelinHubRepo(config);
+ assertThat(repository.getZeppelinhubWebsocketUri(config)).isEqualTo("wss://www.zeppelinhub.com:4242/async");
+ }
+
+ @Test
+ public void testGetAllNotes() throws IOException {
+ List<NoteInfo> notebooks = repo.list(auth);
+ assertThat(notebooks).isNotEmpty();
+ assertThat(notebooks.size()).isEqualTo(3);
+ }
+
+ @Test
+ public void testGetNote() throws IOException {
+ Note notebook = repo.get("AAAAA", auth);
+ assertThat(notebook).isNotNull();
+ assertThat(notebook.getId()).isEqualTo("2A94M5J1Z");
+ }
+
+ @Test
+ public void testRemoveNote() throws IOException {
+ // not suppose to throw
+ repo.remove("AAAAA", auth);
+ }
+
+ @Test
+ public void testRemoveNoteError() throws IOException {
+ // not suppose to throw
+ repo.remove("BBBBB", auth);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinClientTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinClientTest.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinClientTest.java
new file mode 100644
index 0000000..b8e52e4
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinClientTest.java
@@ -0,0 +1,127 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub.websocket;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.mock.MockEchoWebsocketServer;
+import org.apache.zeppelin.notebook.socket.Message;
+import org.apache.zeppelin.notebook.socket.Message.OP;
+import org.eclipse.jetty.websocket.api.Session;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Maps;
+
+public class ZeppelinClientTest {
+ private Logger LOG = LoggerFactory.getLogger(ZeppelinClientTest.class);
+ private final int zeppelinPort = 8080;
+ private final String validWebsocketUrl = "ws://localhost:" + zeppelinPort + "/ws";
+ private ExecutorService executor;
+ private MockEchoWebsocketServer echoServer;
+
+ @Before
+ public void setUp() throws Exception {
+ startWebsocketServer();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ //tear down routine
+ echoServer.stop();
+ executor.shutdown();
+ }
+
+ private void startWebsocketServer() throws InterruptedException {
+ // mock zeppelin websocket server setup
+ executor = Executors.newFixedThreadPool(1);
+ echoServer = new MockEchoWebsocketServer(zeppelinPort);
+ executor.submit(echoServer);
+ }
+
+ @Test
+ public void zeppelinConnectionTest() {
+ try {
+ // Wait for websocket server to start
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ LOG.warn("Cannot wait for websocket server to start, returning");
+ return;
+ }
+ // Initialize and start Zeppelin client
+ ZeppelinClient client = ZeppelinClient.initialize(validWebsocketUrl, "dummy token", null);
+ client.start();
+ LOG.info("Zeppelin websocket client started");
+
+ // Connection to note AAAA
+ Session connectionA = client.getZeppelinConnection("AAAA", "anonymous", "anonymous");
+ assertNotNull(connectionA);
+ assertTrue(connectionA.isOpen());
+
+ assertEquals(client.countConnectedNotes(), 1);
+ assertEquals(connectionA, client.getZeppelinConnection("AAAA", "anonymous", "anonymous"));
+
+ // Connection to note BBBB
+ Session connectionB = client.getZeppelinConnection("BBBB", "anonymous", "anonymous");
+ assertNotNull(connectionB);
+ assertTrue(connectionB.isOpen());
+
+ assertEquals(client.countConnectedNotes(), 2);
+ assertEquals(connectionB, client.getZeppelinConnection("BBBB", "anonymous", "anonymous"));
+
+ // Remove connection to note AAAA
+ client.removeNoteConnection("AAAA");
+ assertEquals(client.countConnectedNotes(), 1);
+ assertNotEquals(connectionA, client.getZeppelinConnection("AAAA", "anonymous", "anonymous"));
+ assertEquals(client.countConnectedNotes(), 2);
+ client.stop();
+ }
+
+ @Test
+ public void zeppelinClientSingletonTest() {
+ ZeppelinClient client1 = ZeppelinClient.getInstance();
+ if (client1 == null) {
+ client1 = ZeppelinClient.initialize(validWebsocketUrl, "TOKEN", null);
+ }
+ assertNotNull(client1);
+ ZeppelinClient client2 = ZeppelinClient.getInstance();
+ assertNotNull(client2);
+ assertEquals(client1, client2);
+ }
+
+ @Test
+ public void zeppelinMessageSerializationTest() {
+ Message msg = new Message(OP.LIST_NOTES);
+ msg.data = Maps.newHashMap();
+ msg.data.put("key", "value");
+ ZeppelinClient client = ZeppelinClient.initialize(validWebsocketUrl, "TOKEN", null);
+ String serializedMsg = client.serialize(msg);
+ Message deserializedMsg = client.deserialize(serializedMsg);
+ assertEquals(msg.op, deserializedMsg.op);
+ assertEquals(msg.data.get("key"), deserializedMsg.data.get("key"));
+
+ String invalidMsg = "random text";
+ deserializedMsg =client.deserialize(invalidMsg);
+ assertNull(deserializedMsg);
+ }
+
+ @Test
+ public void sendToZeppelinTest() {
+ ZeppelinClient client = ZeppelinClient.initialize(validWebsocketUrl, "TOKEN", null);
+ client.start();
+ Message msg = new Message(OP.LIST_NOTES);
+ msg.data = Maps.newHashMap();
+ msg.data.put("key", "value");
+ client.send(msg, "DDDD");
+ client.removeNoteConnection("DDDD");
+ client.stop();
+ }
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinhubClientTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinhubClientTest.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinhubClientTest.java
new file mode 100644
index 0000000..384cfe4
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/ZeppelinhubClientTest.java
@@ -0,0 +1,72 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub.websocket;
+
+import static org.junit.Assert.*;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.ZeppelinhubClient;
+import org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.mock.MockEchoWebsocketServer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ZeppelinhubClientTest {
+ private Logger LOG = LoggerFactory.getLogger(ZeppelinClientTest.class);
+ private final int zeppelinPort = 8090;
+ private final String validWebsocketUrl = "ws://localhost:" + zeppelinPort + "/ws";
+ private ExecutorService executor;
+ private MockEchoWebsocketServer echoServer;
+ private final String runNotebookMsg =
+ "{\"op\":\"RUN_NOTEBOOK\"," +
+ "\"data\":[{\"id\":\"20150112-172845_1301897143\",\"title\":null,\"config\":{},\"params\":{},\"data\":null}," +
+ "{\"id\":\"20150112-172845_1301897143\",\"title\":null,\"config\":{},\"params\":{},\"data\":null}]," +
+ "\"meta\":{\"owner\":\"author\",\"instance\":\"my-zepp\",\"noteId\":\"2AB7SY361\"}}";
+ private final String invalidRunNotebookMsg = "some random string";
+
+ @Before
+ public void setUp() throws Exception {
+ startWebsocketServer();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ //tear down routine
+ echoServer.stop();
+ executor.shutdown();
+ }
+
+ private void startWebsocketServer() throws InterruptedException {
+ // mock zeppelin websocket server setup
+ executor = Executors.newFixedThreadPool(1);
+ echoServer = new MockEchoWebsocketServer(zeppelinPort);
+ executor.submit(echoServer);
+ }
+
+ @Test
+ public void zeppelinhubClientSingletonTest() {
+ ZeppelinhubClient client1 = ZeppelinhubClient.getInstance();
+ if (client1 == null) {
+ client1 = ZeppelinhubClient.initialize(validWebsocketUrl, "TOKEN");
+ }
+ assertNotNull(client1);
+ ZeppelinhubClient client2 = ZeppelinhubClient.getInstance();
+ assertNotNull(client2);
+ assertEquals(client1, client2);
+ }
+
+ @Test
+ public void runAllParagraphTest() throws Exception {
+ Client.initialize(validWebsocketUrl, validWebsocketUrl, "TOKEN", null);
+ Client.getInstance().start();
+ ZeppelinhubClient zeppelinhubClient = ZeppelinhubClient.getInstance();
+ boolean runStatus = zeppelinhubClient.runAllParagraph("2AB7SY361", runNotebookMsg);
+ assertTrue(runStatus);
+ runStatus = zeppelinhubClient.runAllParagraph("2AB7SY361", invalidRunNotebookMsg);
+ assertFalse(runStatus);
+ Client.getInstance().stop();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEchoWebsocketServer.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEchoWebsocketServer.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEchoWebsocketServer.java
new file mode 100644
index 0000000..e9959e9
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEchoWebsocketServer.java
@@ -0,0 +1,46 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.mock;
+
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.slf4j.LoggerFactory;
+
+public class MockEchoWebsocketServer implements Runnable {
+ private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(MockEchoWebsocketServer.class);
+ private Server server;
+
+ public MockEchoWebsocketServer(int port) {
+ server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(port);
+ server.addConnector(connector);
+
+ ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
+ context.setContextPath("/");
+ server.setHandler(context);
+
+ //ServletHolder holderEvents = new ServletHolder("ws-events", MockEventServlet.class);
+ context.addServlet(MockEventServlet.class, "/ws/*");
+ }
+
+ public void start() throws Exception {
+ LOG.info("Starting mock echo websocket server");
+ server.start();
+ server.join();
+ }
+
+ public void stop() throws Exception {
+ LOG.info("Stopping mock echo websocket server");
+ server.stop();
+ }
+
+ @Override
+ public void run() {
+ try {
+ this.start();
+ } catch (Exception e) {
+ LOG.error("Couldn't start mock echo websocket server", e);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventServlet.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventServlet.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventServlet.java
new file mode 100644
index 0000000..c84f2c3
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventServlet.java
@@ -0,0 +1,14 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.mock;
+
+import org.eclipse.jetty.websocket.servlet.WebSocketServlet;
+import org.eclipse.jetty.websocket.servlet.WebSocketServletFactory;
+
+@SuppressWarnings("serial")
+public class MockEventServlet extends WebSocketServlet
+{
+ @Override
+ public void configure(WebSocketServletFactory factory)
+ {
+ factory.register(MockEventSocket.class);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventSocket.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventSocket.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventSocket.java
new file mode 100644
index 0000000..0f39b01
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/mock/MockEventSocket.java
@@ -0,0 +1,38 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.mock;
+
+import org.eclipse.jetty.websocket.api.Session;
+import org.eclipse.jetty.websocket.api.WebSocketAdapter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MockEventSocket extends WebSocketAdapter {
+ private static final Logger LOG = LoggerFactory.getLogger(MockEventServlet.class);
+ private Session session;
+
+ @Override
+ public void onWebSocketConnect(Session session) {
+ super.onWebSocketConnect(session);
+ this.session = session;
+ LOG.info("Socket Connected: " + session);
+ }
+
+ @Override
+ public void onWebSocketText(String message) {
+ super.onWebSocketText(message);
+ session.getRemote().sendStringByFuture(message);
+ LOG.info("Received TEXT message: {}", message);
+
+ }
+
+ @Override
+ public void onWebSocketClose(int statusCode, String reason) {
+ super.onWebSocketClose(statusCode, reason);
+ LOG.info("Socket Closed: [{}] {}", statusCode, reason);
+ }
+
+ @Override
+ public void onWebSocketError(Throwable cause) {
+ super.onWebSocketError(cause);
+ LOG.error("Websocket error: {}", cause);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/protocol/ZeppelinhubMessageTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/protocol/ZeppelinhubMessageTest.java b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/protocol/ZeppelinhubMessageTest.java
new file mode 100644
index 0000000..1f07f4f
--- /dev/null
+++ b/zeppelin-plugins/notebookrepo/zeppelin-hub/src/main/test/org/apache/zeppelin/notebook/repo/zeppelinhub/websocket/protocol/ZeppelinhubMessageTest.java
@@ -0,0 +1,43 @@
+package org.apache.zeppelin.notebook.repo.zeppelinhub.websocket.protocol;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.apache.zeppelin.notebook.socket.Message.OP;
+import org.junit.Test;
+
+import com.google.common.collect.Maps;
+
+public class ZeppelinhubMessageTest {
+
+ private String msg = "{\"op\":\"LIST_NOTES\",\"data\":\"my data\",\"meta\":{\"key1\":\"val1\"}}";
+
+ @Test
+ public void testThatCanSerializeZeppelinHubMessage() {
+ Map<String,String> meta = Maps.newHashMap();
+ meta.put("key1", "val1");
+ String zeppelinHubMsg = ZeppelinhubMessage.newMessage(OP.LIST_NOTES, "my data", meta).toJson();
+
+ assertEquals(msg, zeppelinHubMsg);
+ }
+
+ @Test
+ public void testThastCanDeserialiseZeppelinhubMessage() {
+ Map<String,String> meta = Maps.newHashMap();
+ meta.put("key1", "val1");
+ ZeppelinhubMessage expected = ZeppelinhubMessage.newMessage(OP.LIST_NOTES.toString(), "my data", meta);
+ ZeppelinhubMessage zeppelinHubMsg = ZeppelinhubMessage.fromJson(msg);
+
+ assertEquals(expected.op, zeppelinHubMsg.op);
+ assertEquals(expected.data, zeppelinHubMsg.data);
+ assertEquals(expected.meta, zeppelinHubMsg.meta);
+ }
+
+ @Test
+ public void testThatInvalidStringReturnEmptyZeppelinhubMessage() {
+ assertEquals(ZeppelinhubMessage.EMPTY, ZeppelinhubMessage.fromJson(""));
+ assertEquals(ZeppelinhubMessage.EMPTY, ZeppelinhubMessage.fromJson("dwfewewrewr"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-plugins/pom.xml
----------------------------------------------------------------------
diff --git a/zeppelin-plugins/pom.xml b/zeppelin-plugins/pom.xml
new file mode 100644
index 0000000..f436411
--- /dev/null
+++ b/zeppelin-plugins/pom.xml
@@ -0,0 +1,124 @@
+<?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>
+ <artifactId>zeppelin</artifactId>
+ <groupId>org.apache.zeppelin</groupId>
+ <version>0.9.0-SNAPSHOT</version>
+ <relativePath>..</relativePath>
+ </parent>
+
+ <groupId>org.apache.zeppelin</groupId>
+ <artifactId>zengine-plugins-parent</artifactId>
+ <packaging>pom</packaging>
+ <version>0.9.0-SNAPSHOT</version>
+ <name>Zeppelin: Plugins Parent</name>
+ <description>Zeppelin Plugins Parent</description>
+
+ <modules>
+ <module>notebookrepo/s3</module>
+ <module>notebookrepo/vfs</module>
+ <module>notebookrepo/git</module>
+ <module>notebookrepo/github</module>
+ <module>notebookrepo/azure</module>
+ <module>notebookrepo/gcs</module>
+ <module>notebookrepo/mongodb</module>
+ <module>notebookrepo/zeppelin-hub</module>
+ <module>notebookrepo/filesystem</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>zeppelin-zengine</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- Test libraries -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-plugin-dependencies</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/../../../../plugins/${plugin.name}</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>false</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <includeScope>runtime</includeScope>
+ </configuration>
+ </execution>
+ <execution>
+ <id>copy-plugin-artifact</id>
+ <phase>package</phase>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/../../../../plugins/${plugin.name}</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>false</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <artifactItems>
+ <artifactItem>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${project.artifactId}</artifactId>
+ <version>${project.version}</version>
+ <type>${project.packaging}</type>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-server/pom.xml
----------------------------------------------------------------------
diff --git a/zeppelin-server/pom.xml b/zeppelin-server/pom.xml
index 3ee83bd..fc6d0dd 100644
--- a/zeppelin-server/pom.xml
+++ b/zeppelin-server/pom.xml
@@ -420,42 +420,6 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-antrun-plugin</artifactId>
- <executions>
- <execution>
- <id>start-zeppelin</id>
- <phase>pre-integration-test</phase>
- <configuration>
- <target unless="skipTests">
- <exec executable="./zeppelin-daemon.sh" dir="${zeppelin.daemon.package.base}" spawn="true">
- <arg value="start" />
- </exec>
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
-
- <execution>
- <id>stop-zeppelin</id>
- <phase>post-integration-test</phase>
- <configuration>
- <target unless="skipTests">
- <exec executable="./zeppelin-daemon.sh" dir="${zeppelin.daemon.package.base}" spawn="false">
- <arg value="stop" />
- </exec>
- </target>
- </configuration>
- <goals>
- <goal>run</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
</plugin>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-server/src/main/java/org/apache/zeppelin/realm/PamRealm.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/realm/PamRealm.java b/zeppelin-server/src/main/java/org/apache/zeppelin/realm/PamRealm.java
index 5b3ae10..d7f62ec 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/realm/PamRealm.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/realm/PamRealm.java
@@ -43,7 +43,7 @@ import java.util.Set;
*/
public class PamRealm extends AuthorizingRealm {
- private static final Logger LOG = LoggerFactory.getLogger(ZeppelinHubRealm.class);
+ private static final Logger LOG = LoggerFactory.getLogger(PamRealm.class);
private String service;
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-server/src/main/java/org/apache/zeppelin/realm/ZeppelinHubRealm.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/realm/ZeppelinHubRealm.java b/zeppelin-server/src/main/java/org/apache/zeppelin/realm/ZeppelinHubRealm.java
index 113469f..1d6cdf9 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/realm/ZeppelinHubRealm.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/realm/ZeppelinHubRealm.java
@@ -88,23 +88,23 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
LOG.debug("{} successfully login via ZeppelinHub", user.login);
return new SimpleAuthenticationInfo(user.login, token.getPassword(), name);
}
-
+
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// TODO(xxx): future work will be done here.
return null;
}
-
+
protected void onInit() {
super.onInit();
}
-
+
/**
* Setter of ZeppelinHub URL, this will be called by Shiro based on zeppelinhubUrl property
* in shiro.ini file.</p>
- * It will also perform a check of ZeppelinHub url {@link #isZeppelinHubUrlValid},
+ * It will also perform a check of ZeppelinHub url {@link #isZeppelinHubUrlValid},
* if the url is not valid, the default zeppelinhub url will be used.
- *
+ *
* @param url
*/
public void setZeppelinhubUrl(String url) {
@@ -118,9 +118,9 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
}
/**
- * Send to ZeppelinHub a login request based on the request body which is a JSON that contains 2
+ * Send to ZeppelinHub a login request based on the request body which is a JSON that contains 2
* fields "login" and "password".
- *
+ *
* @param requestBody JSON string of ZeppelinHub payload.
* @return Account object with login, name (if set in ZeppelinHub), and mail.
* @throws AuthenticationException if fail to login.
@@ -141,12 +141,12 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
responseBody = put.getResponseBodyAsString();
userSession = put.getResponseHeader(USER_SESSION_HEADER).getValue();
put.releaseConnection();
-
+
} catch (IOException e) {
LOG.error("Cannot login user", e);
throw new AuthenticationException(e.getMessage());
}
-
+
User account = null;
try {
account = User.fromJson(responseBody);
@@ -156,7 +156,7 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
}
onLoginSuccess(account.login, userSession);
-
+
return account;
}
@@ -182,7 +182,7 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
* Perform a Simple URL check by using <code>URI(url).toURL()</code>.
* If the url is not valid, the try-catch condition will catch the exceptions and return false,
* otherwise true will be returned.
- *
+ *
* @param url
* @return
*/
@@ -215,7 +215,7 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
return gson.fromJson(json, User.class);
}
}
-
+
public void onLoginSuccess(String username, String session) {
UserSessionContainer.instance.setSession(username, session);
@@ -227,7 +227,7 @@ public class ZeppelinHubRealm extends AuthorizingRealm {
ZeppelinhubUtils.userLoginRoutine(username);
}
-
+
@Override
public void onLogout(PrincipalCollection principals) {
ZeppelinhubUtils.userLogoutRoutine((String) principals.getPrimaryPrincipal());
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
index b8f9be9..85fc631 100644
--- a/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
+++ b/zeppelin-server/src/main/java/org/apache/zeppelin/socket/NotebookServer.java
@@ -30,7 +30,6 @@ import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
-import org.apache.commons.vfs2.FileSystemException;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
import org.apache.zeppelin.display.*;
@@ -1052,7 +1051,7 @@ public class NotebookServer extends WebSocketServlet
note.persist(subject);
addConnectionToNote(note.getId(), (NotebookSocket) conn);
conn.send(serializeMessage(new Message(OP.NEW_NOTE).put("note", note)));
- } catch (FileSystemException e) {
+ } catch (IOException e) {
LOG.error("Exception from createNote", e);
conn.send(serializeMessage(new Message(OP.ERROR_INFO).put("info",
"Oops! There is something wrong with the notebook file system. "
@@ -1840,7 +1839,7 @@ public class NotebookServer extends WebSocketServlet
try {
note.persist(p.getAuthenticationInfo());
return true;
- } catch (FileSystemException ex) {
+ } catch (IOException ex) {
LOG.error("Exception from run", ex);
conn.send(serializeMessage(new Message(OP.ERROR_INFO).put("info",
"Oops! There is something wrong with the notebook file system. "
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-server/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/zeppelin-server/src/test/resources/log4j.properties b/zeppelin-server/src/test/resources/log4j.properties
index aff3b79..ce9bc50 100644
--- a/zeppelin-server/src/test/resources/log4j.properties
+++ b/zeppelin-server/src/test/resources/log4j.properties
@@ -41,5 +41,4 @@ log4j.logger.DataNucleus.Datastore=ERROR
# Log all JDBC parameters
log4j.logger.org.hibernate.type=ALL
-
-log4j.logger.org.apache.hadoop=WARN
+log4j.logger.org.apache.hadoop=WARN
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-zengine/pom.xml
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/pom.xml b/zeppelin-zengine/pom.xml
index a7d9d5f..d37f6ea 100644
--- a/zeppelin-zengine/pom.xml
+++ b/zeppelin-zengine/pom.xml
@@ -38,18 +38,13 @@
<!--library versions-->
<hadoop.version>2.7.3</hadoop.version>
<commons.lang3.version>3.4</commons.lang3.version>
- <commons.vfs2.version>2.0</commons.vfs2.version>
- <gcs.storage.version>1.14.0</gcs.storage.version>
- <aws.sdk.s3.version>1.10.62</aws.sdk.s3.version>
- <adl.sdk.version>2.1.4</adl.sdk.version>
<jackrabbit.webdav.version>1.5.2</jackrabbit.webdav.version>
<quartz.scheduler.version>2.2.1</quartz.scheduler.version>
<lucene.version>5.3.1</lucene.version>
<org.reflections.version>0.9.8</org.reflections.version>
<xml.apis.version>1.4.01</xml.apis.version>
- <eclipse.jgit.version>4.5.4.201711221230-r</eclipse.jgit.version>
<frontend.maven.plugin.version>1.3</frontend.maven.plugin.version>
-
+ <aws.sdk.s3.version>1.10.62</aws.sdk.s3.version>
<!--test library versions-->
<google.truth.version>0.27</google.truth.version>
<google.testing.nio.version>0.32.0-alpha</google.testing.nio.version>
@@ -83,15 +78,8 @@
</dependency>
<dependency>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-vfs2</artifactId>
- <version>${commons.vfs2.version}</version>
- <exclusions>
- <exclusion>
- <groupId>org.codehaus.plexus</groupId>
- <artifactId>plexus-utils</artifactId>
- </exclusion>
- </exclusions>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
</dependency>
<dependency>
@@ -117,86 +105,6 @@
</dependency>
<dependency>
- <groupId>com.google.cloud</groupId>
- <artifactId>google-cloud-storage</artifactId>
- <version>${gcs.storage.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.protobuf</groupId>
- <artifactId>protobuf-java</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.api</groupId>
- <artifactId>api-common</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.http-client</groupId>
- <artifactId>google-http-client-jackson2</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.http-client</groupId>
- <artifactId>google-http-client</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-core-asl</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>com.google.api</groupId>
- <artifactId>api-common</artifactId>
- <version>1.2.0</version>
- <exclusions>
- <exclusion>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>com.google.http-client</groupId>
- <artifactId>google-http-client-jackson2</artifactId>
- <version>1.23.0</version>
- <exclusions>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk-s3</artifactId>
- <version>${aws.sdk.s3.version}</version>
- <exclusions>
- <exclusion>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>${jetty.version}</version>
@@ -250,6 +158,12 @@
</dependency>
<dependency>
+ <groupId>com.amazonaws</groupId>
+ <artifactId>aws-java-sdk-s3</artifactId>
+ <version>${aws.sdk.s3.version}</version>
+ </dependency>
+
+ <dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>${org.reflections.version}</version>
@@ -266,12 +180,6 @@
</dependency>
<dependency>
- <groupId>org.eclipse.jgit</groupId>
- <artifactId>org.eclipse.jgit</artifactId>
- <version>${eclipse.jgit.version}</version>
- </dependency>
-
- <dependency>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>${frontend.maven.plugin.version}</version>
@@ -304,23 +212,6 @@
</dependency>
<dependency>
- <groupId>com.google.cloud</groupId>
- <artifactId>google-cloud-nio</artifactId>
- <version>${google.testing.nio.version}</version>
- <scope>test</scope>
- <exclusions>
- <exclusion>
- <groupId>com.google.code.findbugs</groupId>
- <artifactId>jsr305</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
- <dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
<version>${google.truth.version}</version>
@@ -366,12 +257,6 @@
<version>1.5</version>
</dependency>
- <dependency>
- <groupId>org.mongodb</groupId>
- <artifactId>mongo-java-driver</artifactId>
- <version>3.4.1</version>
- </dependency>
-
</dependencies>
<build>
@@ -745,73 +630,6 @@
</exclusion>
</exclusions>
</dependency>
-
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-azure</artifactId>
- <version>${hadoop.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-lang3</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.jcraf</groupId>
- <artifactId>jsch</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-compress</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>com.microsoft.azure</groupId>
- <artifactId>azure-data-lake-store-sdk</artifactId>
- <version>${adl.sdk.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-aws</artifactId>
- <version>${hadoop.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </exclusion>
- <exclusion>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
-
</dependencies>
</profile>
@@ -837,104 +655,6 @@
<version>${hadoop.version}</version>
<scope>test</scope>
</dependency>
-
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-azure</artifactId>
- <version>${hadoop.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.google.guava</groupId>
- <artifactId>guava</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.jcraft</groupId>
- <artifactId>jsch</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.commons</groupId>
- <artifactId>commons-compress</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-mapper-asl</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.nimbusds</groupId>
- <artifactId>nimbus-jose-jwt</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.zookeeper</groupId>
- <artifactId>zookeeper</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-server</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-servlet</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.codehaus.jackson</groupId>
- <artifactId>jackson-core-asl</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.sun.jersey</groupId>
- <artifactId>jersey-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-azure-datalake</artifactId>
- <version>${hadoop.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.hadoop</groupId>
- <artifactId>hadoop-aws</artifactId>
- <version>${hadoop.version}</version>
- <exclusions>
- <exclusion>
- <groupId>com.amazonaws</groupId>
- <artifactId>aws-java-sdk</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </exclusion>
- <exclusion>
- <groupId>joda-time</groupId>
- <artifactId>joda-time</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
</dependencies>
</profile>
</profiles>
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/recovery/FileSystemRecoveryStorage.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/recovery/FileSystemRecoveryStorage.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/recovery/FileSystemRecoveryStorage.java
index 9b1b6cb..4fc860d 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/recovery/FileSystemRecoveryStorage.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/recovery/FileSystemRecoveryStorage.java
@@ -18,13 +18,7 @@
package org.apache.zeppelin.interpreter.recovery;
import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.fs.PathFilter;
-import org.apache.hadoop.io.IOUtils;
-import org.apache.hadoop.security.UserGroupInformation;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.interpreter.InterpreterSetting;
import org.apache.zeppelin.interpreter.InterpreterSettingManager;
@@ -34,15 +28,10 @@ import org.apache.zeppelin.interpreter.remote.RemoteInterpreterEventPoller;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterProcess;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterRunningProcess;
import org.apache.zeppelin.notebook.FileSystemStorage;
-import org.apache.zeppelin.notebook.repo.FileSystemNotebookRepo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java
index 85a5f1c..3728cd3 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Note.java
@@ -167,6 +167,11 @@ public class Note implements ParagraphJobListener, JsonSerializable {
return id;
}
+ @VisibleForTesting
+ public void setId(String id) {
+ this.id = id;
+ }
+
public String getName() {
if (isNameEmpty()) {
name = getId();
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
index ba83449..e9903c7 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Notebook.java
@@ -233,7 +233,7 @@ public class Notebook implements NoteEventListener {
* @throws IOException, CloneNotSupportedException, IllegalArgumentException
*/
public Note cloneNote(String sourceNoteId, String newNoteName, AuthenticationInfo subject)
- throws IOException, CloneNotSupportedException, IllegalArgumentException {
+ throws IOException, IllegalArgumentException {
Note sourceNote = getNote(sourceNoteId);
if (sourceNote == null) {
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java
deleted file mode 100644
index 3b01088..0000000
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/AzureNotebookRepo.java
+++ /dev/null
@@ -1,209 +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.zeppelin.notebook.repo;
-
-import com.microsoft.azure.storage.CloudStorageAccount;
-import com.microsoft.azure.storage.StorageException;
-import com.microsoft.azure.storage.file.CloudFile;
-import com.microsoft.azure.storage.file.CloudFileClient;
-import com.microsoft.azure.storage.file.CloudFileDirectory;
-import com.microsoft.azure.storage.file.CloudFileShare;
-import com.microsoft.azure.storage.file.ListFileItem;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.net.URISyntaxException;
-import java.security.InvalidKeyException;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-import org.apache.zeppelin.conf.ZeppelinConfiguration;
-import org.apache.zeppelin.notebook.Note;
-import org.apache.zeppelin.notebook.NoteInfo;
-import org.apache.zeppelin.user.AuthenticationInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Azure storage backend for notebooks
- */
-public class AzureNotebookRepo implements NotebookRepo {
- private static final Logger LOG = LoggerFactory.getLogger(S3NotebookRepo.class);
-
- private final ZeppelinConfiguration conf;
- private final String user;
- private final String shareName;
- private final CloudFileDirectory rootDir;
-
- public AzureNotebookRepo(ZeppelinConfiguration conf)
- throws URISyntaxException, InvalidKeyException, StorageException {
- this.conf = conf;
- user = conf.getString(ZeppelinConfiguration.ConfVars.ZEPPELIN_NOTEBOOK_AZURE_USER);
- shareName = conf.getString(ZeppelinConfiguration.ConfVars.ZEPPELIN_NOTEBOOK_AZURE_SHARE);
-
- CloudStorageAccount account = CloudStorageAccount.parse(
- conf.getString(ZeppelinConfiguration.ConfVars.ZEPPELIN_NOTEBOOK_AZURE_CONNECTION_STRING));
- CloudFileClient client = account.createCloudFileClient();
- CloudFileShare share = client.getShareReference(shareName);
- share.createIfNotExists();
-
- CloudFileDirectory userDir = StringUtils.isBlank(user) ?
- share.getRootDirectoryReference() :
- share.getRootDirectoryReference().getDirectoryReference(user);
- userDir.createIfNotExists();
-
- rootDir = userDir.getDirectoryReference("notebook");
- rootDir.createIfNotExists();
- }
-
- @Override
- public List<NoteInfo> list(AuthenticationInfo subject) throws IOException {
- List<NoteInfo> infos = new LinkedList<>();
- NoteInfo info = null;
-
- for (ListFileItem item : rootDir.listFilesAndDirectories()) {
- if (item.getClass() == CloudFileDirectory.class) {
- CloudFileDirectory dir = (CloudFileDirectory) item;
-
- try {
- if (dir.getFileReference("note.json").exists()) {
- info = new NoteInfo(getNote(dir.getName()));
-
- if (info != null) {
- infos.add(info);
- }
- }
- } catch (StorageException | URISyntaxException e) {
- String msg = "Error enumerating notebooks from Azure storage";
- LOG.error(msg, e);
- } catch (Exception e) {
- LOG.error(e.getMessage(), e);
- }
- }
- }
-
- return infos;
- }
-
- private Note getNote(String noteId) throws IOException {
- InputStream ins = null;
-
- try {
- CloudFileDirectory dir = rootDir.getDirectoryReference(noteId);
- CloudFile file = dir.getFileReference("note.json");
-
- ins = file.openRead();
- } catch (URISyntaxException | StorageException e) {
- String msg = String.format("Error reading notebook %s from Azure storage", noteId);
-
- LOG.error(msg, e);
-
- throw new IOException(msg, e);
- }
-
- String json = IOUtils.toString(ins,
- conf.getString(ZeppelinConfiguration.ConfVars.ZEPPELIN_ENCODING));
- ins.close();
- return Note.fromJson(json);
- }
-
- @Override
- public Note get(String noteId, AuthenticationInfo subject) throws IOException {
- return getNote(noteId);
- }
-
- @Override
- public void save(Note note, AuthenticationInfo subject) throws IOException {
- String json = note.toJson();
-
- ByteArrayOutputStream output = new ByteArrayOutputStream();
- Writer writer = new OutputStreamWriter(output);
- writer.write(json);
- writer.close();
- output.close();
-
- byte[] buffer = output.toByteArray();
-
- try {
- CloudFileDirectory dir = rootDir.getDirectoryReference(note.getId());
- dir.createIfNotExists();
-
- CloudFile cloudFile = dir.getFileReference("note.json");
- cloudFile.uploadFromByteArray(buffer, 0, buffer.length);
- } catch (URISyntaxException | StorageException e) {
- String msg = String.format("Error saving notebook %s to Azure storage", note.getId());
-
- LOG.error(msg, e);
-
- throw new IOException(msg, e);
- }
- }
-
- // unfortunately, we need to use a recursive delete here
- private void delete(ListFileItem item) throws StorageException {
- if (item.getClass() == CloudFileDirectory.class) {
- CloudFileDirectory dir = (CloudFileDirectory) item;
-
- for (ListFileItem subItem : dir.listFilesAndDirectories()) {
- delete(subItem);
- }
-
- dir.deleteIfExists();
- } else if (item.getClass() == CloudFile.class) {
- CloudFile file = (CloudFile) item;
-
- file.deleteIfExists();
- }
- }
-
- @Override
- public void remove(String noteId, AuthenticationInfo subject) throws IOException {
- try {
- CloudFileDirectory dir = rootDir.getDirectoryReference(noteId);
-
- delete(dir);
- } catch (URISyntaxException | StorageException e) {
- String msg = String.format("Error deleting notebook %s from Azure storage", noteId);
-
- LOG.error(msg, e);
-
- throw new IOException(msg, e);
- }
- }
-
- @Override
- public void close() {
- }
-
- @Override
- public List<NotebookRepoSettingsInfo> getSettings(AuthenticationInfo subject) {
- LOG.warn("Method not implemented");
- return Collections.emptyList();
- }
-
- @Override
- public void updateSettings(Map<String, String> settings, AuthenticationInfo subject) {
- LOG.warn("Method not implemented");
- }
-
-}
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/3eea57ab/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/FileSystemNotebookRepo.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/FileSystemNotebookRepo.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/FileSystemNotebookRepo.java
deleted file mode 100644
index bfc1178..0000000
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/repo/FileSystemNotebookRepo.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package org.apache.zeppelin.notebook.repo;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.io.IOUtils;
-import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.zeppelin.conf.ZeppelinConfiguration;
-import org.apache.zeppelin.notebook.FileSystemStorage;
-import org.apache.zeppelin.notebook.Note;
-import org.apache.zeppelin.notebook.NoteInfo;
-import org.apache.zeppelin.user.AuthenticationInfo;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.security.PrivilegedExceptionAction;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-/**
- * NotebookRepos for hdfs.
- *
- * Assume the notebook directory structure is as following
- * - notebookdir
- * - noteId/note.json
- * - noteId/note.json
- * - noteId/note.json
- */
-public class FileSystemNotebookRepo implements NotebookRepo {
- private static final Logger LOGGER = LoggerFactory.getLogger(FileSystemNotebookRepo.class);
-
- private FileSystemStorage fs;
- private Path notebookDir;
-
- public FileSystemNotebookRepo(ZeppelinConfiguration zConf) throws IOException {
- this.fs = new FileSystemStorage(zConf, zConf.getNotebookDir());
- LOGGER.info("Creating FileSystem: " + this.fs.getFs().getClass().getName() +
- " for Zeppelin Notebook.");
- this.notebookDir = this.fs.makeQualified(new Path(zConf.getNotebookDir()));
- LOGGER.info("Using folder {} to store notebook", notebookDir);
- this.fs.tryMkDir(notebookDir);
- }
-
- @Override
- public List<NoteInfo> list(AuthenticationInfo subject) throws IOException {
- List<Path> notePaths = fs.list(new Path(notebookDir, "*/note.json"));
- List<NoteInfo> noteInfos = new ArrayList<>();
- for (Path path : notePaths) {
- NoteInfo noteInfo = new NoteInfo(path.getParent().getName(), "", null);
- noteInfos.add(noteInfo);
- }
- return noteInfos;
- }
-
- @Override
- public Note get(final String noteId, AuthenticationInfo subject) throws IOException {
- String content = this.fs.readFile(
- new Path(notebookDir.toString() + "/" + noteId + "/note.json"));
- return Note.fromJson(content);
- }
-
- @Override
- public void save(final Note note, AuthenticationInfo subject) throws IOException {
- this.fs.writeFile(note.toJson(),
- new Path(notebookDir.toString() + "/" + note.getId() + "/note.json"),
- true);
- }
-
- @Override
- public void remove(final String noteId, AuthenticationInfo subject) throws IOException {
- this.fs.delete(new Path(notebookDir.toString() + "/" + noteId));
- }
-
- @Override
- public void close() {
- LOGGER.warn("close is not implemented for HdfsNotebookRepo");
- }
-
- @Override
- public List<NotebookRepoSettingsInfo> getSettings(AuthenticationInfo subject) {
- LOGGER.warn("getSettings is not implemented for HdfsNotebookRepo");
- return null;
- }
-
- @Override
- public void updateSettings(Map<String, String> settings, AuthenticationInfo subject) {
- LOGGER.warn("updateSettings is not implemented for HdfsNotebookRepo");
- }
-
-}