Repository: incubator-zeppelin
Updated Branches:
  refs/heads/master e87f5b1ab -> 218a3b5bc


http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
new file mode 100644
index 0000000..8886add
--- /dev/null
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/InterpreterRestApiTest.java
@@ -0,0 +1,206 @@
+/*
+ * 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.rest;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.httpclient.methods.DeleteMethod;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.PutMethod;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.zeppelin.interpreter.InterpreterSetting;
+import org.apache.zeppelin.notebook.Note;
+import org.apache.zeppelin.notebook.Paragraph;
+import org.apache.zeppelin.scheduler.Job.Status;
+import org.apache.zeppelin.server.ZeppelinServer;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+
+import static org.junit.Assert.*;
+
+/**
+ * Zeppelin interpreter rest api tests
+ */
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class InterpreterRestApiTest extends AbstractTestRestApi {
+  Gson gson = new Gson();
+
+  @BeforeClass
+  public static void init() throws Exception {
+    AbstractTestRestApi.startUp();
+  }
+
+  @AfterClass
+  public static void destroy() throws Exception {
+    AbstractTestRestApi.shutDown();
+  }
+
+  @Test
+  public void getAvailableInterpreters() throws IOException {
+    // when
+    GetMethod get = httpGet("/interpreter");
+
+    // then
+    assertThat(get, isAllowed());
+    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
+    }.getType());
+    Map<String, Object> body = (Map<String, Object>) resp.get("body");
+    
assertEquals(ZeppelinServer.notebook.getInterpreterFactory().getRegisteredInterpreterList().size(),
 body.size());
+    get.releaseConnection();
+  }
+
+  @Test
+  public void getSettings() throws IOException {
+    // when
+    GetMethod get = httpGet("/interpreter/setting");
+
+    // then
+    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
+    }.getType());
+    assertThat(get, isAllowed());
+    get.releaseConnection();
+  }
+
+  @Test
+  public void testSettingsCRUD() throws IOException {
+    // Call Create Setting REST API
+    String jsonRequest = 
"{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"},"
 +
+        
"\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}],"
 +
+        "\"dependencies\":[]}";
+    PostMethod post = httpPost("/interpreter/setting/", jsonRequest);
+    LOG.info("testSettingCRUD create response\n" + 
post.getResponseBodyAsString());
+    assertThat("test create method:", post, isCreated());
+
+    Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
+    }.getType());
+    Map<String, Object> body = (Map<String, Object>) resp.get("body");
+    //extract id from body string {id=2AWMQDNX7, name=md2, group=md,
+    String newSettingId = body.toString().split(",")[0].split("=")[1];
+    post.releaseConnection();
+
+    // Call Update Setting REST API
+    jsonRequest = 
"{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"Otherpropvalue\"},"
 +
+        
"\"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}],"
 +
+        "\"dependencies\":[]}";
+    PutMethod put = httpPut("/interpreter/setting/" + newSettingId, 
jsonRequest);
+    LOG.info("testSettingCRUD update response\n" + 
put.getResponseBodyAsString());
+    assertThat("test update method:", put, isAllowed());
+    put.releaseConnection();
+
+    // Call Delete Setting REST API
+    DeleteMethod delete = httpDelete("/interpreter/setting/" + newSettingId);
+    LOG.info("testSettingCRUD delete response\n" + 
delete.getResponseBodyAsString());
+    assertThat("Test delete method:", delete, isAllowed());
+    delete.releaseConnection();
+  }
+
+  @Test
+  public void testInterpreterAutoBinding() throws IOException {
+    // create note
+    Note note = ZeppelinServer.notebook.createNote();
+
+    // check interpreter is binded
+    GetMethod get = httpGet("/notebook/interpreter/bind/" + note.id());
+    assertThat(get, isAllowed());
+    get.addRequestHeader("Origin", "http://localhost";);
+    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
+    }.getType());
+    List<Map<String, String>> body = (List<Map<String, String>>) 
resp.get("body");
+    assertTrue(0 < body.size());
+
+    get.releaseConnection();
+    //cleanup
+    ZeppelinServer.notebook.removeNote(note.getId());
+  }
+
+  @Test
+  public void testInterpreterRestart() throws IOException, 
InterruptedException {
+    // create new note
+    Note note = ZeppelinServer.notebook.createNote();
+    note.addParagraph();
+    Paragraph p = note.getLastParagraph();
+    Map config = p.getConfig();
+    config.put("enabled", true);
+
+    // run markdown paragraph
+    p.setConfig(config);
+    p.setText("%md markdown");
+    note.run(p.getId());
+    while (p.getStatus() != Status.FINISHED) {
+      Thread.sleep(100);
+    }
+    assertEquals("<p>markdown</p>\n", p.getResult().message());
+
+
+    // restart interpreter
+    for (InterpreterSetting setting : 
note.getNoteReplLoader().getInterpreterSettings()) {
+      if (setting.getName().equals("md")) {
+        // Call Restart Interpreter REST API
+        PutMethod put = httpPut("/interpreter/setting/restart/" + 
setting.id(), "");
+        assertThat("test interpreter restart:", put, isAllowed());
+        put.releaseConnection();
+        break;
+      }
+    }
+
+    // run markdown paragraph, again
+    p = note.addParagraph();
+    p.setConfig(config);
+    p.setText("%md markdown restarted");
+    note.run(p.getId());
+    while (p.getStatus() != Status.FINISHED) {
+      Thread.sleep(100);
+    }
+    assertEquals("<p>markdown restarted</p>\n", p.getResult().message());
+    //cleanup
+    ZeppelinServer.notebook.removeNote(note.getId());
+  }
+
+  @Test
+  public void testListRepository() throws IOException {
+    GetMethod get = httpGet("/interpreter/repository");
+    assertThat(get, isAllowed());
+    get.releaseConnection();
+  }
+
+  @Test
+  public void testAddDeleteRepository() throws IOException {
+    // Call create repository REST API
+    String repoId = "securecentral";
+    String jsonRequest = "{\"id\":\"" + repoId +
+        
"\",\"url\":\"https://repo1.maven.org/maven2\",\"snapshot\":\"false\"}";;
+
+    PostMethod post = httpPost("/interpreter/repository/", jsonRequest);
+    assertThat("Test create method:", post, isCreated());
+    post.releaseConnection();
+
+    // Call delete repository REST API
+    DeleteMethod delete = httpDelete("/interpreter/repository/" + repoId);
+    assertThat("Test delete method:", delete, isAllowed());
+    delete.releaseConnection();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java
 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java
index d8049cc..3c7c7d0 100644
--- 
a/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java
+++ 
b/zeppelin-server/src/test/java/org/apache/zeppelin/rest/ZeppelinRestApiTest.java
@@ -72,124 +72,6 @@ public class ZeppelinRestApiTest extends 
AbstractTestRestApi {
     httpGetRoot.releaseConnection();
   }
 
-
-  @Test
-  public void getAvailableInterpreters() throws IOException {
-    // when
-    GetMethod get = httpGet("/interpreter");
-
-    // then
-    assertThat(get, isAllowed());
-    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
-    }.getType());
-    Map<String, Object> body = (Map<String, Object>) resp.get("body");
-    
assertEquals(ZeppelinServer.notebook.getInterpreterFactory().getRegisteredInterpreterList().size(),
 body.size());
-    get.releaseConnection();
-  }
-
-  @Test
-  public void getSettings() throws IOException {
-    // when
-    GetMethod get = httpGet("/interpreter/setting");
-
-    // then
-    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
-    }.getType());
-    assertThat(get, isAllowed());
-    get.releaseConnection();
-  }
-
-  @Test
-  public void testSettingsCRUD() throws IOException {
-    // Call Create Setting REST API
-    String jsonRequest = 
"{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"propvalue\"},\""
 +
-        
"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]}";
-    PostMethod post = httpPost("/interpreter/setting/", jsonRequest);
-    LOG.info("testSettingCRUD create response\n" + 
post.getResponseBodyAsString());
-    assertThat("test create method:", post, isCreated());
-
-    Map<String, Object> resp = gson.fromJson(post.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>() {
-    }.getType());
-    Map<String, Object> body = (Map<String, Object>) resp.get("body");
-    //extract id from body string {id=2AWMQDNX7, name=md2, group=md,
-    String newSettingId =  body.toString().split(",")[0].split("=")[1];
-    post.releaseConnection();
-
-    // Call Update Setting REST API
-    jsonRequest = 
"{\"name\":\"md2\",\"group\":\"md\",\"properties\":{\"propname\":\"Otherpropvalue\"},\""
 +
-        
"interpreterGroup\":[{\"class\":\"org.apache.zeppelin.markdown.Markdown\",\"name\":\"md\"}]}";
-    PutMethod put = httpPut("/interpreter/setting/" + newSettingId, 
jsonRequest);
-    LOG.info("testSettingCRUD update response\n" + 
put.getResponseBodyAsString());
-    assertThat("test update method:", put, isAllowed());
-    put.releaseConnection();
-
-    // Call Delete Setting REST API
-    DeleteMethod delete = httpDelete("/interpreter/setting/" + newSettingId);
-    LOG.info("testSettingCRUD delete response\n" + 
delete.getResponseBodyAsString());
-    assertThat("Test delete method:", delete, isAllowed());
-    delete.releaseConnection();
-  }
-  @Test
-  public void testInterpreterAutoBinding() throws IOException {
-    // create note
-    Note note = ZeppelinServer.notebook.createNote();
-
-    // check interpreter is binded
-    GetMethod get = httpGet("/notebook/interpreter/bind/"+note.id());
-    assertThat(get, isAllowed());
-    get.addRequestHeader("Origin", "http://localhost";);
-    Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), 
new TypeToken<Map<String, Object>>(){}.getType());
-    List<Map<String, String>> body = (List<Map<String, String>>) 
resp.get("body");
-    assertTrue(0 < body.size());
-
-    get.releaseConnection();
-    //cleanup
-    ZeppelinServer.notebook.removeNote(note.getId());
-  }
-
-  @Test
-  public void testInterpreterRestart() throws IOException, 
InterruptedException {
-    // create new note
-    Note note = ZeppelinServer.notebook.createNote();
-    note.addParagraph();
-    Paragraph p = note.getLastParagraph();
-    Map config = p.getConfig();
-    config.put("enabled", true);
-
-    // run markdown paragraph
-    p.setConfig(config);
-    p.setText("%md markdown");
-    note.run(p.getId());
-    while (p.getStatus() != Status.FINISHED) {
-      Thread.sleep(100);
-    }
-    assertEquals("<p>markdown</p>\n", p.getResult().message());
-
-    
-    // restart interpreter
-    for (InterpreterSetting setting : 
note.getNoteReplLoader().getInterpreterSettings()) {
-      if (setting.getName().equals("md")) {
-        // Call Restart Interpreter REST API
-        PutMethod put = httpPut("/interpreter/setting/restart/" + 
setting.id(), "");
-        assertThat("test interpreter restart:", put, isAllowed());
-        put.releaseConnection();
-        break;
-      }
-    }
-
-    // run markdown paragraph, again
-    p = note.addParagraph();
-    p.setConfig(config);
-    p.setText("%md markdown restarted");
-    note.run(p.getId());
-    while (p.getStatus() != Status.FINISHED) {
-      Thread.sleep(100);
-    }
-    assertEquals("<p>markdown restarted</p>\n", p.getResult().message());
-    //cleanup
-    ZeppelinServer.notebook.removeNote(note.getId());
-  }
-
   @Test
   public void testGetNotebookInfo() throws IOException {
     LOG.info("testGetNotebookInfo");
@@ -303,7 +185,7 @@ public class ZeppelinRestApiTest extends 
AbstractTestRestApi {
   }
 
   @Test
-  public void  testDeleteNote() throws IOException {
+  public void testDeleteNote() throws IOException {
     LOG.info("testDeleteNote");
     //Create note and get ID
     Note note = ZeppelinServer.notebook.createNote();

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/app/app.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/app.js b/zeppelin-web/src/app/app.js
index d13faf0..33a9daf 100644
--- a/zeppelin-web/src/app/app.js
+++ b/zeppelin-web/src/app/app.js
@@ -81,7 +81,8 @@
             ngToastProvider.configure({
                 dismissButton: true,
                 dismissOnClick: false,
-                timeout: 6000
+                timeout: 6000,
+                verticalPosition: 'bottom'
             });
         });
 

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/app/home/home.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/home/home.css 
b/zeppelin-web/src/app/home/home.css
index 0202142..dada898 100644
--- a/zeppelin-web/src/app/home/home.css
+++ b/zeppelin-web/src/app/home/home.css
@@ -276,31 +276,6 @@ kbd {
 }
 
 /*
-  ngToast Style
-*/
-
-.ng-toast .alert {
-  color: white !important;
-  border: none !important;
-}
-
-.ng-toast .alert-danger {
-  background: #A94442 !important;
-}
-
-.ng-toast .alert-warning {
-  background: #CE9532 !important;
-}
-
-.ng-toast .alert-info {
-  background: #589EC1 !important;
-}
-
-.ng-toast .alert-success {
-  background: #428443 !important;
-}
-
-/*
 temporary fix for bootstrap issue 
(https://github.com/twbs/bootstrap/issues/5865)
 This part should be removed when new version of bootstrap handles this issue.
 */

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
----------------------------------------------------------------------
diff --git 
a/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html 
b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
index 38ae7cc..6f46c4e 100644
--- 
a/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
+++ 
b/zeppelin-web/src/app/interpreter/interpreter-create/interpreter-create.html
@@ -12,10 +12,10 @@ See the License for the specific language governing 
permissions and
 limitations under the License.
 -->
 <div>
-  <div class="row">
-    <div class="col-md-12">
-      <div class="interpreterSettingAdd" ng-show="showAddNewSetting">
-        <hr />
+  <div class="row interpreter">
+    <div class="col-md-12" ng-show="showAddNewSetting">
+      <hr />
+      <div class="interpreterSettingAdd">
         <h4>Create new interpreter</h4>
 
         <div class="form-group" style="width:200px">
@@ -67,6 +67,50 @@ limitations under the License.
           </tr>
         </table>
 
+        <b>Dependencies</b>
+        <table class="table table-striped properties">
+          <tr>
+            <th>artifact</th>
+            <th>exclude</th>
+            <th>action</th>
+          </tr>
+
+          <tr ng-repeat="dep in newInterpreterSetting.dependencies">
+            <td>
+              <input ng-model="dep.groupArtifactVersion" style="width:100%" />
+            </td>
+            <td>
+              <textarea msd-elastic ng-model="dep.exclusions"
+                        ng-list
+                        placeholder="(Optional) comma separated 
groupId:artifactId list">
+              </textarea>
+            </td>
+            <td>
+              <div class="btn btn-default btn-sm fa fa-remove"
+                   
ng-click="removeInterpreterDependency(dep.groupArtifactVersion)">
+              </div>
+            </td>
+          </tr>
+
+          <tr>
+            <td>
+              <input ng-model="newInterpreterSetting.depArtifact"
+                     placeholder="groupId:artifactId:version or local file 
path"
+                     style="width: 100%" />
+            </td>
+            <td>
+              <textarea msd-elastic ng-model="newInterpreterSetting.depExclude"
+                        ng-list
+                        placeholder="(Optional) comma separated 
groupId:artifactId list">
+              </textarea>
+            </td>
+            <td>
+              <div class="btn btn-default btn-sm fa fa-plus" 
ng-click="addNewInterpreterDependency()">
+              </div>
+            </td>
+          </tr>
+        </table>
+
         <span class="btn btn-primary" ng-click="addNewInterpreterSetting()">
           Save
         </span>

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/app/interpreter/interpreter.controller.js
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/interpreter/interpreter.controller.js 
b/zeppelin-web/src/app/interpreter/interpreter.controller.js
index 396a552..1e3800a 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.controller.js
+++ b/zeppelin-web/src/app/interpreter/interpreter.controller.js
@@ -15,37 +15,42 @@
 'use strict';
 
 angular.module('zeppelinWebApp').controller('InterpreterCtrl', 
function($scope, $route, $routeParams, $location, $rootScope,
-                                                                         
$http, baseUrlSrv) {
+                                                                         
$http, baseUrlSrv, ngToast) {
   var interpreterSettingsTmp = [];
   $scope.interpreterSettings = [];
   $scope.availableInterpreters = {};
   $scope.showAddNewSetting = false;
+  $scope.showRepositoryInfo = false;
   $scope._ = _;
 
   var getInterpreterSettings = function() {
     $http.get(baseUrlSrv.getRestApiBase()+'/interpreter/setting').
-    success(function(data, status, headers, config) {
-      $scope.interpreterSettings = data.body;
-    }).
-    error(function(data, status, headers, config) {
-      console.log('Error %o %o', status, data.message);
-    });
+      success(function(data, status, headers, config) {
+        $scope.interpreterSettings = data.body;
+      }).
+      error(function(data, status, headers, config) {
+        console.log('Error %o %o', status, data.message);
+      });
   };
 
   var getAvailableInterpreters = function() {
     $http.get(baseUrlSrv.getRestApiBase()+'/interpreter').
-    success(function(data, status, headers, config) {
-      $scope.availableInterpreters = data.body;
-    }).
-    error(function(data, status, headers, config) {
-      console.log('Error %o %o', status, data.message);
-    });
+      success(function(data, status, headers, config) {
+        $scope.availableInterpreters = data.body;
+      }).
+      error(function(data, status, headers, config) {
+        console.log('Error %o %o', status, data.message);
+      });
   };
 
   var emptyNewProperty = function(object) {
     angular.extend(object, {propertyValue: '', propertyKey: ''});
   };
 
+  var emptyNewDependency = function(object) {
+    angular.extend(object, {depArtifact: '', depExclude: ''});
+  };
+
   var removeTMPSettings = function(index) {
     interpreterSettingsTmp.splice(index, 1);
   };
@@ -55,29 +60,34 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
     interpreterSettingsTmp[index] = 
angular.copy($scope.interpreterSettings[index]);
   };
 
-  $scope.updateInterpreterSetting = function(settingId) {
-    BootstrapDialog.confirm({
-      closable: true,
-      title: '',
-      message: 'Do you want to update this interpreter and restart with new 
settings?',
-      callback: function(result) {
-        if (result) {
-          var index = _.findIndex($scope.interpreterSettings, {'id': 
settingId});
-          var request = {
-            properties: 
angular.copy($scope.interpreterSettings[index].properties),
-          };
-
-          $http.put(baseUrlSrv.getRestApiBase() + '/interpreter/setting/' + 
settingId, request).
-            success(function (data, status, headers, config) {
-              $scope.interpreterSettings[index] = data.body;
-              removeTMPSettings(index);
-            }).
-            error(function (data, status, headers, config) {
-              console.log('Error %o %o', status, data.message);
-            });
-        }
+  $scope.updateInterpreterSetting = function(form, settingId) {
+    var result = confirm('Do you want to update this interpreter and restart 
with new settings?');
+    if (result) {
+      var index = _.findIndex($scope.interpreterSettings, {'id': settingId});
+      var setting = $scope.interpreterSettings[index];
+      if (setting.propertyKey !== '' || setting.propertyKey) {
+        $scope.addNewInterpreterProperty(settingId);
       }
-    });
+      if (setting.depArtifact !== '' || setting.depArtifact) {
+        $scope.addNewInterpreterDependency(settingId);
+      }
+
+      var request = {
+        properties: angular.copy(setting.properties),
+        dependencies: angular.copy(setting.dependencies)
+      };
+
+      $http.put(baseUrlSrv.getRestApiBase() + '/interpreter/setting/' + 
settingId, request).
+        success(function (data, status, headers, config) {
+          $scope.interpreterSettings[index] = data.body;
+          removeTMPSettings(index);
+        }).
+        error(function (data, status, headers, config) {
+          console.log('Error %o %o', status, data.message);
+          ngToast.danger(data.message);
+          form.$show();
+        });
+    }
   };
 
   $scope.resetInterpreterSetting = function(settingId){
@@ -117,8 +127,8 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
       var intpInfo = el[i];
       for (var key in intpInfo) {
         properties[key] = {
-          value : intpInfo[key].defaultValue,
-          description : intpInfo[key].description
+          value: intpInfo[key].defaultValue,
+          description: intpInfo[key].description
         };
       }
     }
@@ -165,32 +175,46 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
       return;
     }
 
-    var newSetting = angular.copy($scope.newInterpreterSetting);
+    var newSetting = $scope.newInterpreterSetting;
+    if (newSetting.propertyKey !== '' || newSetting.propertyKey) {
+      $scope.addNewInterpreterProperty();
+    }
+    if (newSetting.depArtifact !== '' || newSetting.depArtifact) {
+      $scope.addNewInterpreterDependency();
+    }
+
+    var request = angular.copy($scope.newInterpreterSetting);
 
-    for (var p in $scope.newInterpreterSetting.properties) {
-      newSetting.properties[p] = 
$scope.newInterpreterSetting.properties[p].value;
+    // Change properties to proper request format
+    var newProperties = {};
+    for (var p in newSetting.properties) {
+      newProperties[p] = newSetting.properties[p].value;
     }
+    request.properties = newProperties;
 
-    $http.post(baseUrlSrv.getRestApiBase()+'/interpreter/setting', newSetting).
-    success(function(data, status, headers, config) {
-      $scope.resetNewInterpreterSetting();
-      getInterpreterSettings();
-      $scope.showAddNewSetting = false;
-    }).
-    error(function(data, status, headers, config) {
-      console.log('Error %o %o', status, data.message);
-    });
+    $http.post(baseUrlSrv.getRestApiBase() + '/interpreter/setting', request).
+      success(function(data, status, headers, config) {
+        $scope.resetNewInterpreterSetting();
+        getInterpreterSettings();
+        $scope.showAddNewSetting = false;
+      }).
+      error(function(data, status, headers, config) {
+        console.log('Error %o %o', status, data.message);
+        ngToast.danger(data.message);
+      });
   };
 
   $scope.cancelInterpreterSetting = function() {
     $scope.showAddNewSetting = false;
+    $scope.resetNewInterpreterSetting();
   };
 
   $scope.resetNewInterpreterSetting = function() {
     $scope.newInterpreterSetting = {
-      name : undefined,
-      group : undefined,
-      properties : {}
+      name: undefined,
+      group: undefined,
+      properties: {},
+      dependencies: []
     };
     emptyNewProperty($scope.newInterpreterSetting);
   };
@@ -205,6 +229,21 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
     }
   };
 
+  $scope.removeInterpreterDependency = function(artifact, settingId) {
+    if (settingId === undefined) {
+      $scope.newInterpreterSetting.dependencies = 
_.reject($scope.newInterpreterSetting.dependencies,
+        function(el) {
+          return el.groupArtifactVersion === artifact;
+        });
+    } else {
+      var index = _.findIndex($scope.interpreterSettings, {'id': settingId});
+      $scope.interpreterSettings[index].dependencies = 
_.reject($scope.interpreterSettings[index].dependencies,
+        function(el) {
+          return el.groupArtifactVersion === artifact;
+        });
+    }
+  };
+
   $scope.addNewInterpreterProperty = function(settingId) {
     if(settingId === undefined) {
       // Add new property from create form
@@ -230,10 +269,126 @@ 
angular.module('zeppelinWebApp').controller('InterpreterCtrl', function($scope,
     }
   };
 
+  $scope.addNewInterpreterDependency = function(settingId) {
+    if(settingId === undefined) {
+      // Add new dependency from create form
+      if (!$scope.newInterpreterSetting.depArtifact || 
$scope.newInterpreterSetting.depArtifact === '') {
+        return;
+      }
+
+      // overwrite if artifact already exists
+      var newSetting = $scope.newInterpreterSetting;
+      for(var d in newSetting.dependencies) {
+        if (newSetting.dependencies[d].groupArtifactVersion === 
newSetting.depArtifact) {
+          newSetting.dependencies[d] = {
+            'groupArtifactVersion': newSetting.depArtifact,
+            'exclusions': newSetting.depExclude
+          };
+          newSetting.dependencies.splice(d, 1);
+        }
+      }
+
+      newSetting.dependencies.push({
+        'groupArtifactVersion': newSetting.depArtifact,
+        'exclusions': (newSetting.depExclude === '')? []: newSetting.depExclude
+      });
+      emptyNewDependency(newSetting);
+    }
+    else {
+      // Add new dependency from edit form
+      var index = _.findIndex($scope.interpreterSettings, { 'id': settingId });
+      var setting = $scope.interpreterSettings[index];
+      if (!setting.depArtifact || setting.depArtifact === '') {
+        return;
+      }
+
+      // overwrite if artifact already exists
+      for(var dep in setting.dependencies) {
+        if (setting.dependencies[dep].groupArtifactVersion === 
setting.depArtifact) {
+          setting.dependencies[dep] = {
+            'groupArtifactVersion': setting.depArtifact,
+            'exclusions': setting.depExclude
+          };
+          setting.dependencies.splice(dep, 1);
+        }
+      }
+
+      setting.dependencies.push({
+        'groupArtifactVersion': setting.depArtifact,
+        'exclusions': (setting.depExclude === '')? []: setting.depExclude
+      });
+      emptyNewDependency(setting);
+    }
+  };
+
+  $scope.resetNewRepositorySetting = function() {
+    $scope.newRepoSetting = {
+      id: undefined,
+      url: undefined,
+      snapshot: false,
+      username: undefined,
+      password: undefined
+    };
+  };
+
+  var getRepositories = function() {
+    $http.get(baseUrlSrv.getRestApiBase() + '/interpreter/repository').
+      success(function(data, status, headers, config) {
+        $scope.repositories = data.body;
+      }).
+      error(function(data, status, headers, config) {
+        console.log('Error %o %o', status, data.message);
+      });
+  };
+
+  $scope.addNewRepository = function() {
+    var request = angular.copy($scope.newRepoSetting);
+
+    $http.post(baseUrlSrv.getRestApiBase() + '/interpreter/repository', 
request).
+      success(function(data, status, headers, config) {
+        getRepositories();
+        $scope.resetNewRepositorySetting();
+        angular.element('#repoModal').modal('hide');
+      }).
+      error(function(data, status, headers, config) {
+        console.log('Error %o %o', headers, config);
+      });
+  };
+
+  $scope.removeRepository = function(repoId) {
+    BootstrapDialog.confirm({
+      closable: true,
+      title: '',
+      message: 'Do you want to delete this repository?',
+      callback: function(result) {
+        if (result) {
+          $http.delete(baseUrlSrv.getRestApiBase()+'/interpreter/repository/' 
+ repoId).
+            success(function(data, status, headers, config) {
+              var index = _.findIndex($scope.repositories, { 'id': repoId });
+              $scope.repositories.splice(index, 1);
+            }).
+            error(function(data, status, headers, config) {
+              console.log('Error %o %o', status, data.message);
+            });
+        }
+      }
+    });
+  };
+
+  $scope.isDefaultRepository = function(repoId) {
+    if (repoId === 'central' || repoId === 'local') {
+      return true;
+    } else {
+      return false;
+    }
+  };
+
   var init = function() {
     $scope.resetNewInterpreterSetting();
+    $scope.resetNewRepositorySetting();
     getInterpreterSettings();
     getAvailableInterpreters();
+    getRepositories();
   };
 
   init();

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/app/interpreter/interpreter.css
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/interpreter/interpreter.css 
b/zeppelin-web/src/app/interpreter/interpreter.css
index b6fe133..8695f94 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.css
+++ b/zeppelin-web/src/app/interpreter/interpreter.css
@@ -34,6 +34,13 @@
   font-size: 12px;
 }
 
+.interpreter input {
+  width: 100%;
+  display: block;
+  height: 23px;
+  border: 1px solid #CCCCCC;
+}
+
 .interpreter .interpreter-title {
   font-size: 20px;
   font-weight: bold;
@@ -81,6 +88,11 @@
   float: left;
 }
 
-.empty-properties-message {
+.gray40-message {
   color: #666;
 }
+
+.blackOpc:hover {
+  color: #000;
+  opacity: .5;
+}

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/app/interpreter/interpreter.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/app/interpreter/interpreter.html 
b/zeppelin-web/src/app/interpreter/interpreter.html
index 57984da..f1f9a02 100644
--- a/zeppelin-web/src/app/interpreter/interpreter.html
+++ b/zeppelin-web/src/app/interpreter/interpreter.html
@@ -18,11 +18,18 @@ limitations under the License.
         <h3 class="new_h3">
           Interpreters
         </h3>
-        <span class="btn btn-default fa fa-plus"
-              ng-click="showAddNewSetting = !showAddNewSetting"
-              style="float:right;margin-top:10px;">
-          Create
-        </span>
+        <div class="pull-right" style="margin-top:10px;">
+          <span class="btn btn-default fa fa-plus"
+                ng-click="showAddNewSetting = !showAddNewSetting"
+                style="margin-right:6px;">
+            Create
+          </span>
+          <span style="cursor:pointer;margin-right:4px;"
+                ng-click="showRepositoryInfo = !showRepositoryInfo"
+                tooltip-placement="bottom" tooltip="Repository information">
+            <i class="fa fa-cog" ng-style="{color: showRepositoryInfo ? 
'#3071A9' : 'black' }"></i>
+          </span>
+        </div>
       </div>
     </div>
     <div class="row">
@@ -31,6 +38,42 @@ limitations under the License.
       </div>
     </div>
   </div>
+
+  <div class="row" ng-if="showRepositoryInfo">
+    <div class="col-md-12">
+      <hr />
+      <h4>Repositories</h4>
+      <p>Available repository lists. These repositories are used to resolve 
external dependencies of interpreter.</p>
+      <ul class="noDot">
+        <li class="liVertical" ng-repeat="repo in repositories">
+          <a tabindex="0" class="btn btn-info" role="button"
+             popover-trigger="focus"
+             popover-placement="right"
+             popover-html-unsafe="
+               <label>URL: </label>
+               {{repo.url}}<br>
+               <label>Snapshot: </label>
+               {{repo.snapshotPolicy.enabled}}<br>
+               <label>Username: </label>
+               {{repo.authentication.username}}">
+            <span class="fa fa-database"></span>
+            {{repo.id}}&nbsp;
+            <span ng-if="!isDefaultRepository(repo.id)"
+                  class="fa fa-close blackOpc" 
ng-click="removeRepository(repo.id)"></span>
+          </a>
+        </li>
+        <li class="liVertical">
+          <div ng-include 
src="'components/repository-create/repository-dialog.html'"></div>
+          <div class="btn btn-default"
+               data-toggle="modal"
+               data-target="#repoModal">
+            <span class="fa fa-plus"></span>
+          </div>
+        </li>
+      </ul>
+    </div>
+  </div>
+
   <div ng-include 
src="'app/interpreter/interpreter-create/interpreter-create.html'"></div>
 </div>
 
@@ -66,8 +109,8 @@ limitations under the License.
       </div>
     </div>
     <div class="row interpreter">
-      <div ng-show="_.isEmpty(setting.properties) || valueform.$hidden" 
class="col-md-12 empty-properties-message">
-        <em>Currently there are no properties set for this interpreter</em>
+      <div ng-show="_.isEmpty(setting.properties) && 
_.isEmpty(setting.dependencies) || valueform.$hidden" class="col-md-12 
gray40-message">
+        <em>Currently there are no properties and dependencies set for this 
interpreter</em>
       </div>
       <div class="col-md-12" ng-show="!_.isEmpty(setting.properties) || 
valueform.$visible">
         <h5>Properties</h5>
@@ -96,8 +139,7 @@ limitations under the License.
             <td>
               <input ng-model="setting.propertyKey"
                      pu-elastic-input
-                     pu-elastic-input-minwidth="180px">
-              </input>
+                     pu-elastic-input-minwidth="180px" />
             </td>
             <td>
               <textarea msd-elastic 
ng-model="setting.propertyValue"></textarea>
@@ -109,9 +151,66 @@ limitations under the License.
             </td>
           </tr>
         </table>
-        <form editable-form name="valueform" 
onaftersave="updateInterpreterSetting(setting.id)" ng-show="valueform.$visible">
-          <button type="submit" class="btn btn-primary"
-                  ng-disabled="valueform.$waiting">
+      </div>
+
+      <div class="col-md-12" ng-show="!_.isEmpty(setting.dependencies) || 
valueform.$visible">
+        <h5>Dependencies</h5>
+        <p class="gray40-message" style="font-size:12px" 
ng-show="valueform.$visible">
+          These dependencies will be added to classpath when interpreter 
process starts.</p>
+        <table class="table table-striped">
+          <thead>
+            <tr>
+              <th style="width:40%">artifact</th>
+              <th>exclude</th>
+              <th ng-if="valueform.$visible">action</th>
+            </tr>
+          </thead>
+          <tr ng-repeat="dep in setting.dependencies">
+            <td>
+              <span editable-text="dep.groupArtifactVersion" 
e-placeholder="groupId:artifactId:version or local file path"
+                    e-form="valueform" e-msd-elastic e-style="width:100%">
+                {{dep.groupArtifactVersion | breakFilter}}
+              </span>
+            </td>
+            <td>
+              <textarea ng-if="valueform.$visible" ng-model="dep.exclusions"
+                        placeholder="(Optional) comma separated 
groupId:artifactId list"
+                        form="valueform"
+                        e-msd-elastic
+                        ng-list="">
+              </textarea>
+              <div ng-if="!valueform.$visible">{{dep.exclusions.join()}}</div>
+            </td>
+            <td ng-if="valueform.$visible">
+              <div class="btn btn-default btn-sm fa fa-remove"
+                   
ng-click="removeInterpreterDependency(dep.groupArtifactVersion, setting.id)">
+              </div>
+            </td>
+          </tr>
+          <tr ng-if="valueform.$visible">
+            <td>
+              <input ng-model="setting.depArtifact"
+                     placeholder="groupId:artifactId:version or local file 
path"
+                     style="width: 100%" />
+            </td>
+            <td>
+              <textarea ng-model="setting.depExclude"
+                        placeholder="(Optional) comma separated 
groupId:artifactId list"
+                        msd-elastic
+                        ng-list="">
+              </textarea>
+            </td>
+            <td>
+              <div class="btn btn-default btn-sm fa fa-plus"
+                   ng-click="addNewInterpreterDependency(setting.id)">
+              </div>
+            </td>
+          </tr>
+        </table>
+        <form editable-form name="valueform"
+              onaftersave="updateInterpreterSetting(valueform, setting.id)"
+              ng-show="valueform.$visible">
+          <button type="submit" class="btn btn-primary">
             Save
           </button>
           <button type="button" class="btn btn-default"

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/components/repository-create/repository-dialog.html
----------------------------------------------------------------------
diff --git 
a/zeppelin-web/src/components/repository-create/repository-dialog.html 
b/zeppelin-web/src/components/repository-create/repository-dialog.html
new file mode 100644
index 0000000..98b1469
--- /dev/null
+++ b/zeppelin-web/src/components/repository-create/repository-dialog.html
@@ -0,0 +1,76 @@
+<!--
+Licensed 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.
+-->
+
+<div id="repoModal" class="modal fade" role="dialog"
+     tabindex='-1'>
+  <div class="modal-dialog">
+
+    <!-- Modal content-->
+    <div class="modal-content">
+      <div class="modal-header">
+        <button type="button" class="close" 
data-dismiss="modal">&times;</button>
+        <h4 class="modal-title">Add New Repository</h4>
+      </div>
+
+      <form class="form-horizontal" ng-submit="addNewRepository()">
+        <div class="modal-body">
+            <div class="form-group">
+              <label class="control-label col-sm-2" for="repoId">ID</label>
+              <div class="col-sm-10">
+                <input type="text" class="form-control" id="repoId" 
ng-model="newRepoSetting.id"
+                       placeholder="Repository id" required>
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2" for="repoUrl">URL</label>
+              <div class="col-sm-10">
+                <input type="text" pattern="(http|https|file)://.*" 
title="Please enter URL starts with http://, https:// or file://"
+                       class="form-control" id="repoUrl" 
ng-model="newRepoSetting.url"
+                       placeholder="Repository url" required>
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2" 
for="repoSnapshot">Snapshot</label>
+              <div class="col-sm-10">
+                <select class="form-control" id="repoSnapshot" 
ng-model="newRepoSetting.snapshot">
+                  <option ng-selected="true">false</option>
+                  <option>true</option>
+                </select>
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2" 
for="repoUsername">Username</label>
+              <div class="col-sm-10">
+                <input type="text" class="form-control" id="repoUsername" 
ng-model="newRepoSetting.username">
+              </div>
+            </div>
+            <div class="form-group">
+              <label class="control-label col-sm-2" 
for="repoPassword">Password</label>
+              <div class="col-sm-10">
+                <input type="password" class="form-control" id="repoPassword" 
ng-model="newRepoSetting.password">
+              </div>
+            </div>
+        </div>
+        <div class="modal-footer">
+          <button type="submit"
+                  class="btn btn-default">Add
+          </button>
+          <button type="button" data-dismiss="modal"
+                  class="btn btn-default" 
ng-click="resetNewRepositorySetting()">Cancel
+          </button>
+        </div>
+      </form>
+    </div>
+  </div>
+</div>

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-web/src/index.html
----------------------------------------------------------------------
diff --git a/zeppelin-web/src/index.html b/zeppelin-web/src/index.html
index a8e082c..1f1166b 100644
--- a/zeppelin-web/src/index.html
+++ b/zeppelin-web/src/index.html
@@ -63,8 +63,8 @@ limitations under the License.
   </head>
   <body ng-class="{'bodyAsIframe': asIframe}" >
     <!--[if lt IE 7]>
-<p class="browsehappy">You are using an <strong>outdated</strong> browser. 
Please <a href="http://browsehappy.com/";>upgrade your browser</a> to improve 
your experience.</p>
-<![endif]-->
+    <p class="browsehappy">You are using an <strong>outdated</strong> browser. 
Please <a href="http://browsehappy.com/";>upgrade your browser</a> to improve 
your experience.</p>
+    <![endif]-->
     <toast></toast>
     <div ng-include src="'components/navbar/navbar.html'"></div>
     <!-- Add your site or application content here -->
@@ -81,9 +81,9 @@ limitations under the License.
     </div>
     <!-- build:js(.) scripts/oldieshim.js -->
     <!--[if lt IE 9]>
-<script src="bower_components/es5-shim/es5-shim.js"></script>
-<script src="bower_components/json3/lib/json3.min.js"></script>
-<![endif]-->
+    <script src="bower_components/es5-shim/es5-shim.js"></script>
+    <script src="bower_components/json3/lib/json3.min.js"></script>
+    <![endif]-->
     <!-- endbuild -->
 
     <!-- build:js(.) scripts/vendor.js -->

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
index 9e606ee..421b3d4 100755
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/conf/ZeppelinConfiguration.java
@@ -346,6 +346,10 @@ public class ZeppelinConfiguration extends 
XMLConfiguration {
     return getRelativeDir(ConfVars.ZEPPELIN_INTERPRETER_REMOTE_RUNNER);
   }
 
+  public String getInterpreterLocalRepoPath() {
+    return getRelativeDir(ConfVars.ZEPPELIN_INTERPRETER_LOCALREPO);
+  }
+
   public String getRelativeDir(ConfVars c) {
     return getRelativeDir(getString(c));
   }
@@ -456,6 +460,7 @@ public class ZeppelinConfiguration extends XMLConfiguration 
{
         + "org.apache.zeppelin.scalding.ScaldingInterpreter,"
         + "org.apache.zeppelin.jdbc.JDBCInterpreter"),
     ZEPPELIN_INTERPRETER_DIR("zeppelin.interpreter.dir", "interpreter"),
+    ZEPPELIN_INTERPRETER_LOCALREPO("zeppelin.interpreter.localRepo", 
"local-repo"),
     
ZEPPELIN_INTERPRETER_CONNECT_TIMEOUT("zeppelin.interpreter.connect.timeout", 
30000),
     ZEPPELIN_INTERPRETER_MAX_POOL_SIZE("zeppelin.interpreter.max.poolsize", 
10),
     ZEPPELIN_ENCODING("zeppelin.encoding", "UTF-8"),

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
index 3cd1257..3761709 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterFactory.java
@@ -19,10 +19,13 @@ package org.apache.zeppelin.interpreter;
 
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+
+import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.NullArgumentException;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
+import org.apache.zeppelin.dep.Dependency;
 import org.apache.zeppelin.dep.DependencyResolver;
 import org.apache.zeppelin.display.AngularObjectRegistry;
 import org.apache.zeppelin.display.AngularObjectRegistryListener;
@@ -34,6 +37,9 @@ import org.apache.zeppelin.scheduler.Job;
 import org.apache.zeppelin.scheduler.Job.Status;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonatype.aether.RepositoryException;
+import org.sonatype.aether.repository.Authentication;
+import org.sonatype.aether.repository.RemoteRepository;
 
 import java.io.*;
 import java.lang.reflect.Constructor;
@@ -60,6 +66,7 @@ public class InterpreterFactory {
       new HashMap<String, InterpreterSetting>();
 
   private Map<String, List<String>> interpreterBindings = new HashMap<String, 
List<String>>();
+  private List<RemoteRepository> interpreterRepositories;
 
   private Gson gson;
 
@@ -68,13 +75,13 @@ public class InterpreterFactory {
   AngularObjectRegistryListener angularObjectRegistryListener;
   private final RemoteInterpreterProcessListener 
remoteInterpreterProcessListener;
 
-  DependencyResolver depResolver;
+  private DependencyResolver depResolver;
 
   public InterpreterFactory(ZeppelinConfiguration conf,
       AngularObjectRegistryListener angularObjectRegistryListener,
       RemoteInterpreterProcessListener remoteInterpreterProcessListener,
       DependencyResolver depResolver)
-      throws InterpreterException, IOException {
+      throws InterpreterException, IOException, RepositoryException {
     this(conf, new InterpreterOption(true), angularObjectRegistryListener,
             remoteInterpreterProcessListener, depResolver);
   }
@@ -84,11 +91,12 @@ public class InterpreterFactory {
       AngularObjectRegistryListener angularObjectRegistryListener,
       RemoteInterpreterProcessListener remoteInterpreterProcessListener,
       DependencyResolver depResolver)
-      throws InterpreterException, IOException {
+      throws InterpreterException, IOException, RepositoryException {
     this.conf = conf;
     this.defaultOption = defaultOption;
     this.angularObjectRegistryListener = angularObjectRegistryListener;
     this.depResolver = depResolver;
+    this.interpreterRepositories = depResolver.getRepos();
     this.remoteInterpreterProcessListener = remoteInterpreterProcessListener;
     String replsConf = conf.getString(ConfVars.ZEPPELIN_INTERPRETERS);
     interpreterClassList = replsConf.split(",");
@@ -101,7 +109,7 @@ public class InterpreterFactory {
     init();
   }
 
-  private void init() throws InterpreterException, IOException {
+  private void init() throws InterpreterException, IOException, 
RepositoryException {
     ClassLoader oldcl = Thread.currentThread().getContextClassLoader();
 
     // Load classes
@@ -172,7 +180,11 @@ public class InterpreterFactory {
 
             if (found) {
               // add all interpreters in group
-              add(groupName, groupName, defaultOption, p);
+              add(groupName,
+                  groupName,
+                  new LinkedList<Dependency>(),
+                  defaultOption,
+                  p);
               groupClassNameMap.remove(groupName);
               break;
             }
@@ -186,7 +198,7 @@ public class InterpreterFactory {
       logger.info("Interpreter setting group {} : id={}, name={}",
           setting.getGroup(), settingId, setting.getName());
       for (Interpreter interpreter : setting.getInterpreterGroup()) {
-        logger.info("  className = {}", interpreter.getClassName());
+        logger.info(" className = {}", interpreter.getClassName());
       }
     }
   }
@@ -225,12 +237,11 @@ public class InterpreterFactory {
       // previously created setting should turn this feature on here.
       setting.getOption().setRemote(true);
 
-
-
       InterpreterSetting intpSetting = new InterpreterSetting(
           setting.id(),
           setting.getName(),
           setting.getGroup(),
+          setting.getDependencies(),
           setting.getOption());
 
       InterpreterGroup interpreterGroup = createInterpreterGroup(
@@ -244,8 +255,41 @@ public class InterpreterFactory {
     }
 
     this.interpreterBindings = info.interpreterBindings;
+
+    if (info.interpreterRepositories != null) {
+      for (RemoteRepository repo : info.interpreterRepositories) {
+        if (!depResolver.getRepos().contains(repo)) {
+          this.interpreterRepositories.add(repo);
+        }
+      }
+    }
   }
 
+  private void loadInterpreterDependencies(InterpreterSetting intSetting)
+      throws IOException, RepositoryException {
+    // dependencies to prevent library conflict
+    File localRepoDir = new File(conf.getInterpreterLocalRepoPath() + "/" + 
intSetting.id());
+    if (localRepoDir.exists()) {
+      FileUtils.cleanDirectory(localRepoDir);
+    }
+
+    // load dependencies
+    List<Dependency> deps = intSetting.getDependencies();
+    if (deps != null) {
+      for (Dependency d: deps) {
+        if (d.getExclusions() != null) {
+          depResolver.load(
+              d.getGroupArtifactVersion(),
+              d.getExclusions(),
+              conf.getString(ConfVars.ZEPPELIN_DEP_LOCALREPO) + "/" + 
intSetting.id());
+        } else {
+          depResolver.load(
+              d.getGroupArtifactVersion(),
+              conf.getString(ConfVars.ZEPPELIN_DEP_LOCALREPO) + "/" + 
intSetting.id());
+        }
+      }
+    }
+  }
 
   private void saveToFile() throws IOException {
     String jsonString;
@@ -254,6 +298,7 @@ public class InterpreterFactory {
       InterpreterInfoSaving info = new InterpreterInfoSaving();
       info.interpreterBindings = interpreterBindings;
       info.interpreterSettings = interpreterSettings;
+      info.interpreterRepositories = interpreterRepositories;
 
       jsonString = gson.toJson(info);
     }
@@ -330,15 +375,21 @@ public class InterpreterFactory {
    * @throws IOException
    */
   public InterpreterGroup add(String name, String groupName,
+      List<Dependency> dependencies,
       InterpreterOption option, Properties properties)
-      throws InterpreterException, IOException {
+      throws InterpreterException, IOException, RepositoryException {
     synchronized (interpreterSettings) {
 
       InterpreterSetting intpSetting = new InterpreterSetting(
           name,
           groupName,
+          dependencies,
           option);
 
+      if (dependencies.size() > 0) {
+        loadInterpreterDependencies(intpSetting);
+      }
+
       InterpreterGroup interpreterGroup = createInterpreterGroup(
           intpSetting.id(), groupName, option, properties);
 
@@ -354,13 +405,13 @@ public class InterpreterFactory {
       String groupName,
       InterpreterOption option,
       Properties properties)
-      throws InterpreterException , NullArgumentException {
+      throws InterpreterException, NullArgumentException {
 
     //When called from REST API without option we receive NPE
-    if (option == null )
+    if (option == null)
       throw new NullArgumentException("option");
     //When called from REST API without option we receive NPE
-    if (properties == null )
+    if (properties == null)
       throw new NullArgumentException("properties");
 
     AngularObjectRegistry angularObjectRegistry;
@@ -393,7 +444,8 @@ public class InterpreterFactory {
           if (option.isRemote()) {
             intp = createRemoteRepl(info.getPath(),
                 info.getClassName(),
-                properties);
+                properties,
+                interpreterGroup.id);
           } else {
             intp = createRepl(info.getPath(),
                 info.getClassName(),
@@ -428,6 +480,9 @@ public class InterpreterFactory {
         saveToFile();
       }
     }
+
+    File localRepoDir = new File(conf.getInterpreterLocalRepoPath() + "/" + 
id);
+    FileUtils.deleteDirectory(localRepoDir);
   }
 
   /**
@@ -511,8 +566,10 @@ public class InterpreterFactory {
    * @param properties
    * @throws IOException
    */
-  public void setPropertyAndRestart(String id, InterpreterOption option,
-      Properties properties) throws IOException {
+  public void setPropertyAndRestart(String id,
+      InterpreterOption option,
+      Properties properties,
+      List<Dependency> dependencies) throws IOException, RepositoryException {
     synchronized (interpreterSettings) {
       InterpreterSetting intpsetting = interpreterSettings.get(id);
       if (intpsetting != null) {
@@ -523,11 +580,14 @@ public class InterpreterFactory {
         intpsetting.getInterpreterGroup().destroy();
 
         intpsetting.setOption(option);
+        intpsetting.setDependencies(dependencies);
 
         InterpreterGroup interpreterGroup = createInterpreterGroup(
             intpsetting.id(),
             intpsetting.getGroup(), option, properties);
         intpsetting.setInterpreterGroup(interpreterGroup);
+
+        loadInterpreterDependencies(intpsetting);
         saveToFile();
       } else {
         throw new InterpreterException("Interpreter setting id " + id
@@ -661,13 +721,14 @@ public class InterpreterFactory {
 
 
   private Interpreter createRemoteRepl(String interpreterPath, String 
className,
-      Properties property) {
-
+      Properties property, String interpreterId) {
     int connectTimeout = 
conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_CONNECT_TIMEOUT);
+    String localRepoPath = conf.getInterpreterLocalRepoPath() + "/" + 
interpreterId;
     int maxPoolSize = conf.getInt(ConfVars.ZEPPELIN_INTERPRETER_MAX_POOL_SIZE);
     LazyOpenInterpreter intp = new LazyOpenInterpreter(new RemoteInterpreter(
         property, className, conf.getInterpreterRemoteRunnerPath(),
-        interpreterPath, connectTimeout, maxPoolSize, 
remoteInterpreterProcessListener));
+        interpreterPath, localRepoPath, connectTimeout,
+        maxPoolSize, remoteInterpreterProcessListener));
     return intp;
   }
 
@@ -690,4 +751,19 @@ public class InterpreterFactory {
       return new URL[] {path.toURI().toURL()};
     }
   }
+
+  public List<RemoteRepository> getRepositories() {
+    return this.interpreterRepositories;
+  }
+
+  public void addRepository(String id, String url, boolean snapshot, 
Authentication auth)
+      throws IOException {
+    depResolver.addRepo(id, url, snapshot, auth);
+    saveToFile();
+  }
+
+  public void removeRepository(String id) throws IOException {
+    depResolver.delRepo(id);
+    saveToFile();
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java
index ae507d4..786a723 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterInfoSaving.java
@@ -17,6 +17,8 @@
 
 package org.apache.zeppelin.interpreter;
 
+import org.sonatype.aether.repository.RemoteRepository;
+
 import java.util.List;
 import java.util.Map;
 
@@ -26,4 +28,5 @@ import java.util.Map;
 public class InterpreterInfoSaving {
   public Map<String, InterpreterSetting> interpreterSettings;
   public Map<String, List<String>> interpreterBindings;
+  public List<RemoteRepository> interpreterRepositories;
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
index 301ed23..e8080a2 100644
--- 
a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
+++ 
b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterSetting.java
@@ -17,9 +17,12 @@
 
 package org.apache.zeppelin.interpreter;
 
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Properties;
 import java.util.Random;
 
+import org.apache.zeppelin.dep.Dependency;
 import org.apache.zeppelin.notebook.utility.IdHashes;
 
 /**
@@ -32,21 +35,26 @@ public class InterpreterSetting {
   private String description;
   private Properties properties;
   private InterpreterGroup interpreterGroup;
+  private List<Dependency> dependencies;
   private InterpreterOption option;
 
-  public InterpreterSetting(String id, String name,
+  public InterpreterSetting(String id,
+      String name,
       String group,
+      List<Dependency> dependencies,
       InterpreterOption option) {
     this.id = id;
     this.name = name;
     this.group = group;
+    this.dependencies = dependencies;
     this.option = option;
   }
 
   public InterpreterSetting(String name,
       String group,
+      List<Dependency> dependencies,
       InterpreterOption option) {
-    this(generateId(), name, group, option);
+    this(generateId(), name, group, dependencies, option);
   }
 
   public String id() {
@@ -90,6 +98,17 @@ public class InterpreterSetting {
     return properties;
   }
 
+  public List<Dependency> getDependencies() {
+    if (dependencies == null) {
+      return new LinkedList<Dependency>();
+    }
+    return dependencies;
+  }
+
+  public void setDependencies(List<Dependency> dependencies) {
+    this.dependencies = dependencies;
+  }
+
   public InterpreterOption getOption() {
     if (option == null) {
       option = new InterpreterOption();

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java
 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java
index 17d91cc..8fea693 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/interpreter/InterpreterFactoryTest.java
@@ -24,17 +24,21 @@ import static org.junit.Assert.assertTrue;
 
 import java.io.File;
 import java.io.IOException;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Properties;
 
 import org.apache.commons.lang.NullArgumentException;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
+import org.apache.zeppelin.dep.Dependency;
+import org.apache.zeppelin.dep.DependencyResolver;
 import org.apache.zeppelin.interpreter.mock.MockInterpreter1;
 import org.apache.zeppelin.interpreter.mock.MockInterpreter2;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.sonatype.aether.RepositoryException;
 
 public class InterpreterFactoryTest {
 
@@ -42,6 +46,7 @@ public class InterpreterFactoryTest {
   private File tmpDir;
   private ZeppelinConfiguration conf;
   private InterpreterContext context;
+  private DependencyResolver depResolver;
 
   @Before
   public void setUp() throws Exception {
@@ -55,7 +60,8 @@ public class InterpreterFactoryTest {
     System.setProperty(ConfVars.ZEPPELIN_HOME.getVarName(), 
tmpDir.getAbsolutePath());
     System.setProperty(ConfVars.ZEPPELIN_INTERPRETERS.getVarName(), 
"org.apache.zeppelin.interpreter.mock.MockInterpreter1,org.apache.zeppelin.interpreter.mock.MockInterpreter2");
     conf = new ZeppelinConfiguration();
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, null);
+    depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + 
"/local-repo");
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, depResolver);
     context = new InterpreterContext("note", "id", "title", "text", null, 
null, null, null, null);
 
   }
@@ -98,14 +104,14 @@ public class InterpreterFactoryTest {
   }
 
   @Test
-  public void testFactoryDefaultList() throws IOException {
+  public void testFactoryDefaultList() throws IOException, RepositoryException 
{
     // get default list from default setting
     List<String> all = factory.getDefaultInterpreterSettingList();
     assertEquals(2, all.size());
     
assertEquals(factory.get(all.get(0)).getInterpreterGroup().getFirst().getClassName(),
 "org.apache.zeppelin.interpreter.mock.MockInterpreter1");
 
     // add setting
-    factory.add("a mock", "mock2", new InterpreterOption(false), new 
Properties());
+    factory.add("a mock", "mock2", new LinkedList<Dependency>(), new 
InterpreterOption(false), new Properties());
     all = factory.getDefaultInterpreterSettingList();
     assertEquals(2, all.size());
     assertEquals("mock1", factory.get(all.get(0)).getName());
@@ -113,16 +119,16 @@ public class InterpreterFactoryTest {
   }
 
   @Test
-  public void testExceptions() throws IOException {
+  public void testExceptions() throws InterpreterException, IOException, 
RepositoryException {
     List<String> all = factory.getDefaultInterpreterSettingList();
     // add setting with null option & properties expected 
nullArgumentException.class
     try {
-      factory.add("a mock", "mock2", null, new Properties());
+      factory.add("a mock", "mock2", new LinkedList<Dependency>(), null, new 
Properties());
     } catch(NullArgumentException e) {
       assertEquals("Test null option" , e.getMessage(),new 
NullArgumentException("option").getMessage());
     }
     try {
-      factory.add("a mock" , "mock2" , new InterpreterOption(false),null);
+      factory.add("a mock", "mock2", new LinkedList<Dependency>(), new 
InterpreterOption(false), null);
     } catch (NullArgumentException e){
       assertEquals("Test null properties" , e.getMessage(),new 
NullArgumentException("properties").getMessage());
     }
@@ -130,17 +136,17 @@ public class InterpreterFactoryTest {
 
 
   @Test
-  public void testSaveLoad() throws InterpreterException, IOException {
+  public void testSaveLoad() throws IOException, RepositoryException {
     // interpreter settings
     assertEquals(2, factory.get().size());
 
     // check if file saved
     assertTrue(new File(conf.getInterpreterSettingPath()).exists());
 
-    factory.add("newsetting", "mock1", new InterpreterOption(false), new 
Properties());
+    factory.add("newsetting", "mock1", new LinkedList<Dependency>(), new 
InterpreterOption(false), new Properties());
     assertEquals(3, factory.get().size());
 
-    InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, 
null);
+    InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, 
null, depResolver);
     assertEquals(3, factory2.get().size());
   }
 }

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java
 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java
index 4fa8ef6..04a6ceb 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteInterpreterLoaderTest.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
 
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
+import org.apache.zeppelin.dep.DependencyResolver;
 import org.apache.zeppelin.interpreter.Interpreter;
 import org.apache.zeppelin.interpreter.InterpreterFactory;
 import org.apache.zeppelin.interpreter.InterpreterOption;
@@ -40,6 +41,7 @@ public class NoteInterpreterLoaderTest {
   private File tmpDir;
   private ZeppelinConfiguration conf;
   private InterpreterFactory factory;
+  private DependencyResolver depResolver;
 
   @Before
   public void setUp() throws Exception {
@@ -58,7 +60,8 @@ public class NoteInterpreterLoaderTest {
     MockInterpreter11.register("mock11", "group1", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter11");
     MockInterpreter2.register("mock2", "group2", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter2");
 
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, null);
+    depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + 
"/local-repo");
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, depResolver);
   }
 
   @After

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
index 55cd6ba..1988f1c 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NotebookTest.java
@@ -35,6 +35,7 @@ import java.util.Map;
 import org.apache.commons.io.FileUtils;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
+import org.apache.zeppelin.dep.DependencyResolver;
 import org.apache.zeppelin.display.AngularObjectRegistry;
 import org.apache.zeppelin.interpreter.InterpreterFactory;
 import org.apache.zeppelin.interpreter.InterpreterOption;
@@ -55,6 +56,7 @@ import org.junit.Test;
 import org.quartz.SchedulerException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.sonatype.aether.RepositoryException;
 
 public class NotebookTest implements JobListenerFactory{
   private static final Logger logger = 
LoggerFactory.getLogger(NotebookTest.class);
@@ -66,6 +68,7 @@ public class NotebookTest implements JobListenerFactory{
   private Notebook notebook;
   private NotebookRepo notebookRepo;
   private InterpreterFactory factory;
+  private DependencyResolver depResolver;
 
   @Before
   public void setUp() throws Exception {
@@ -86,7 +89,8 @@ public class NotebookTest implements JobListenerFactory{
     MockInterpreter1.register("mock1", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter1");
     MockInterpreter2.register("mock2", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter2");
 
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, null);
+    depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + 
"/local-repo");
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, depResolver);
 
     SearchService search = mock(SearchService.class);
     notebookRepo = new VFSNotebookRepo(conf);
@@ -161,7 +165,7 @@ public class NotebookTest implements JobListenerFactory{
   }
 
   @Test
-  public void testPersist() throws IOException, SchedulerException{
+  public void testPersist() throws IOException, SchedulerException, 
RepositoryException {
     Note note = notebook.createNote();
 
     // run with default repl
@@ -173,8 +177,8 @@ public class NotebookTest implements JobListenerFactory{
     note.persist();
 
     Notebook notebook2 = new Notebook(
-        conf, notebookRepo, schedulerFactory, new InterpreterFactory(conf, 
null, null, null), this,
-            null);
+        conf, notebookRepo, schedulerFactory,
+        new InterpreterFactory(conf, null, null, null, depResolver), this, 
null);
     assertEquals(1, notebook2.getAllNotes().size());
   }
 

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java
 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java
index 31970af..753fab2 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/NotebookRepoSyncTest.java
@@ -28,6 +28,7 @@ import java.util.Map;
 import org.apache.commons.io.FileUtils;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
+import org.apache.zeppelin.dep.DependencyResolver;
 import org.apache.zeppelin.interpreter.InterpreterFactory;
 import org.apache.zeppelin.interpreter.InterpreterOption;
 import org.apache.zeppelin.interpreter.InterpreterOutput;
@@ -57,6 +58,7 @@ public class NotebookRepoSyncTest implements 
JobListenerFactory {
   private Notebook notebookSync;
   private NotebookRepoSync notebookRepoSync;
   private InterpreterFactory factory;
+  private DependencyResolver depResolver;
   private static final Logger LOG = 
LoggerFactory.getLogger(NotebookRepoSyncTest.class);
   
   @Before
@@ -85,7 +87,8 @@ public class NotebookRepoSyncTest implements 
JobListenerFactory {
     MockInterpreter1.register("mock1", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter1");
     MockInterpreter2.register("mock2", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter2");
 
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, null);
+    depResolver = new DependencyResolver(mainZepDir.getAbsolutePath() + 
"/local-repo");
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, depResolver);
     
     SearchService search = mock(SearchService.class);
     notebookRepoSync = new NotebookRepoSync(conf);

http://git-wip-us.apache.org/repos/asf/incubator-zeppelin/blob/218a3b5b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java
----------------------------------------------------------------------
diff --git 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java
 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java
index 2e2801c..0d4ff86 100644
--- 
a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java
+++ 
b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/repo/VFSNotebookRepoTest.java
@@ -27,6 +27,7 @@ import java.util.Map;
 import org.apache.commons.io.FileUtils;
 import org.apache.zeppelin.conf.ZeppelinConfiguration;
 import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
+import org.apache.zeppelin.dep.DependencyResolver;
 import org.apache.zeppelin.interpreter.InterpreterFactory;
 import org.apache.zeppelin.interpreter.InterpreterOption;
 import org.apache.zeppelin.interpreter.mock.MockInterpreter1;
@@ -48,6 +49,7 @@ public class VFSNotebookRepoTest implements 
JobListenerFactory {
   private Notebook notebook;
   private NotebookRepo notebookRepo;
   private InterpreterFactory factory;
+  private DependencyResolver depResolver;
 
   private File mainZepDir;
   private File mainNotebookDir;
@@ -73,7 +75,8 @@ public class VFSNotebookRepoTest implements 
JobListenerFactory {
     MockInterpreter1.register("mock1", 
"org.apache.zeppelin.interpreter.mock.MockInterpreter1");
 
     this.schedulerFactory = new SchedulerFactory();
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, null);
+    depResolver = new DependencyResolver(mainZepDir.getAbsolutePath() + 
"/local-repo");
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, 
null, depResolver);
 
     SearchService search = mock(SearchService.class);
     notebookRepo = new VFSNotebookRepo(conf);

Reply via email to