zeppelin-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jongy...@apache.org
Subject [2/3] zeppelin git commit: [ZEPPELIN-1210] Run interpreter per user
Date Thu, 20 Oct 2016 06:23:15 GMT
http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/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 5d9f301..19081c9 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
@@ -121,6 +121,8 @@ public class InterpreterFactory implements InterpreterGroupFactory {
 
   private DependencyResolver depResolver;
 
+  private boolean shiroEnabled;
+
   private Map<String, String> env = new HashMap<>();
 
   private Interpreter devInterpreter;
@@ -128,18 +130,18 @@ public class InterpreterFactory implements InterpreterGroupFactory {
   public InterpreterFactory(ZeppelinConfiguration conf,
       AngularObjectRegistryListener angularObjectRegistryListener,
       RemoteInterpreterProcessListener remoteInterpreterProcessListener,
-      ApplicationEventListener appEventListener, DependencyResolver depResolver)
-      throws InterpreterException, IOException, RepositoryException {
+      ApplicationEventListener appEventListener, DependencyResolver depResolver,
+      boolean shiroEnabled) throws InterpreterException, IOException, RepositoryException {
     this(conf, new InterpreterOption(true), angularObjectRegistryListener,
-        remoteInterpreterProcessListener, appEventListener, depResolver);
+        remoteInterpreterProcessListener, appEventListener, depResolver, shiroEnabled);
   }
 
 
   public InterpreterFactory(ZeppelinConfiguration conf, InterpreterOption defaultOption,
       AngularObjectRegistryListener angularObjectRegistryListener,
       RemoteInterpreterProcessListener remoteInterpreterProcessListener,
-      ApplicationEventListener appEventListener, DependencyResolver depResolver)
-      throws InterpreterException, IOException, RepositoryException {
+      ApplicationEventListener appEventListener, DependencyResolver depResolver,
+      boolean shiroEnabled) throws InterpreterException, IOException, RepositoryException {
     this.conf = conf;
     this.defaultOption = defaultOption;
     this.angularObjectRegistryListener = angularObjectRegistryListener;
@@ -147,6 +149,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     this.interpreterRepositories = depResolver.getRepos();
     this.remoteInterpreterProcessListener = remoteInterpreterProcessListener;
     this.appEventListener = appEventListener;
+    this.shiroEnabled = shiroEnabled;
     String replsConf = conf.getString(ConfVars.ZEPPELIN_INTERPRETERS);
     interpreterClassList = replsConf.split(",");
     String groupOrder = conf.getString(ConfVars.ZEPPELIN_INTERPRETER_GROUP_ORDER);
@@ -157,6 +160,8 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     gson = builder.create();
 
     init();
+
+    logger.info("shiroEnabled: {}", shiroEnabled);
   }
 
   private void init() throws InterpreterException, IOException, RepositoryException {
@@ -698,16 +703,18 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     return interpreterGroup;
   }
 
-  public void removeInterpretersForNote(InterpreterSetting interpreterSetting, String noteId) {
-    if (interpreterSetting.getOption().isPerNoteProcess()) {
+  public void removeInterpretersForNote(InterpreterSetting interpreterSetting, String user,
+      String noteId) {
+    InterpreterOption option = interpreterSetting.getOption();
+    if (option.isProcess()) {
       interpreterSetting.closeAndRemoveInterpreterGroup(noteId);
-    } else if (interpreterSetting.getOption().isPerNoteSession()) {
-      InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(noteId);
-
-      interpreterGroup.close(noteId);
-      interpreterGroup.destroy(noteId);
+    } else if (option.isSession()) {
+      InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(user, noteId);
+      String key = getInterpreterInstanceKey(user, noteId, interpreterSetting);
+      interpreterGroup.close(key);
+      interpreterGroup.destroy(key);
       synchronized (interpreterGroup) {
-        interpreterGroup.remove(noteId);
+        interpreterGroup.remove(key);
         interpreterGroup.notifyAll(); // notify createInterpreterForNote()
       }
       logger.info("Interpreter instance {} for note {} is removed", interpreterSetting.getName(),
@@ -715,9 +722,9 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     }
   }
 
-  public void createInterpretersForNote(InterpreterSetting interpreterSetting, String noteId,
-      String key) {
-    InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(noteId);
+  public void createInterpretersForNote(InterpreterSetting interpreterSetting, String user,
+      String noteId, String key) {
+    InterpreterGroup interpreterGroup = interpreterSetting.getInterpreterGroup(user, noteId);
     InterpreterOption option = interpreterSetting.getOption();
     Properties properties = interpreterSetting.getProperties();
     if (option.isExistingProcess) {
@@ -861,8 +868,8 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     }
   }
 
-  private void putNoteInterpreterSettingBinding(String noteId, List<String> settingList)
-      throws IOException {
+  private void putNoteInterpreterSettingBinding(String user, String noteId,
+      List<String> settingList) throws IOException {
     List<String> unBindedSettings = new LinkedList<>();
 
     synchronized (interpreterSettings) {
@@ -879,18 +886,18 @@ public class InterpreterFactory implements InterpreterGroupFactory {
 
       for (String settingId : unBindedSettings) {
         InterpreterSetting setting = get(settingId);
-        removeInterpretersForNote(setting, noteId);
+        removeInterpretersForNote(setting, user, noteId);
       }
     }
   }
 
-  public void removeNoteInterpreterSettingBinding(String noteId) {
+  public void removeNoteInterpreterSettingBinding(String user, String noteId) {
     synchronized (interpreterSettings) {
       List<String> settingIds = (interpreterBindings.containsKey(noteId) ?
           interpreterBindings.remove(noteId) :
           Collections.<String>emptyList());
       for (String settingId : settingIds) {
-        this.removeInterpretersForNote(get(settingId), noteId);
+        this.removeInterpretersForNote(get(settingId), user, noteId);
       }
     }
   }
@@ -1093,8 +1100,8 @@ public class InterpreterFactory implements InterpreterGroupFactory {
    * @param ids    InterpreterSetting id list
    * @throws IOException
    */
-  public void setInterpreters(String noteId, List<String> ids) throws IOException {
-    putNoteInterpreterSettingBinding(noteId, ids);
+  public void setInterpreters(String user, String noteId, List<String> ids) throws IOException {
+    putNoteInterpreterSettingBinding(user, noteId, ids);
   }
 
   public List<String> getInterpreters(String noteId) {
@@ -1119,7 +1126,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     return settings;
   }
 
-  public void closeNote(String noteId) {
+  public void closeNote(String user, String noteId) {
     // close interpreters in this note session
     List<InterpreterSetting> settings = getInterpreterSettings(noteId);
     if (settings == null || settings.size() == 0) {
@@ -1128,28 +1135,37 @@ public class InterpreterFactory implements InterpreterGroupFactory {
 
     logger.info("closeNote: {}", noteId);
     for (InterpreterSetting setting : settings) {
-      removeInterpretersForNote(setting, noteId);
+      removeInterpretersForNote(setting, user, noteId);
     }
   }
 
-  private String getInterpreterInstanceKey(String noteId, InterpreterSetting setting) {
-    if (setting.getOption().isExistingProcess()) {
-      return Constants.EXISTING_PROCESS;
-    } else if (setting.getOption().isPerNoteSession() || setting.getOption().isPerNoteProcess()) {
-      return noteId;
+  private String getInterpreterInstanceKey(String user, String noteId, InterpreterSetting setting) {
+    InterpreterOption option = setting.getOption();
+    String key;
+    if (option.isExistingProcess()) {
+      key = Constants.EXISTING_PROCESS;
+    } else if (!option.perNoteShared()) {
+      key = noteId;
+      if (shiroEnabled && !option.perUserShared()) {
+        key = user + ":" + key;
+      }
     } else {
-      return SHARED_SESSION;
+      key = SHARED_SESSION;
     }
+
+    logger.debug("Interpreter instance key: {}", key);
+    return key;
   }
 
-  private List<Interpreter> createOrGetInterpreterList(String noteId, InterpreterSetting setting) {
-    InterpreterGroup interpreterGroup = setting.getInterpreterGroup(noteId);
+  private List<Interpreter> createOrGetInterpreterList(String user, String noteId,
+      InterpreterSetting setting) {
+    InterpreterGroup interpreterGroup = setting.getInterpreterGroup(user, noteId);
     synchronized (interpreterGroup) {
-      String key = getInterpreterInstanceKey(noteId, setting);
+      String key = getInterpreterInstanceKey(user, noteId, setting);
       if (!interpreterGroup.containsKey(key)) {
-        createInterpretersForNote(setting, noteId, key);
+        createInterpretersForNote(setting, user, noteId, key);
       }
-      return interpreterGroup.get(getInterpreterInstanceKey(noteId, setting));
+      return interpreterGroup.get(getInterpreterInstanceKey(user, noteId, setting));
     }
   }
 
@@ -1190,14 +1206,15 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     return null;
   }
 
-  private Interpreter getInterpreter(String noteId, InterpreterSetting setting, String name) {
+  private Interpreter getInterpreter(String user, String noteId, InterpreterSetting setting,
+      String name) {
     Preconditions.checkNotNull(noteId, "noteId should be not null");
     Preconditions.checkNotNull(setting, "setting should be not null");
     Preconditions.checkNotNull(name, "name should be not null");
 
     String className;
     if (null != (className = getInterpreterClassFromInterpreterSetting(setting, name))) {
-      List<Interpreter> interpreterGroup = createOrGetInterpreterList(noteId, setting);
+      List<Interpreter> interpreterGroup = createOrGetInterpreterList(user, noteId, setting);
       for (Interpreter interpreter : interpreterGroup) {
         if (className.equals(interpreter.getClassName())) {
           return interpreter;
@@ -1207,7 +1224,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     return null;
   }
 
-  public Interpreter getInterpreter(String noteId, String replName) {
+  public Interpreter getInterpreter(String user, String noteId, String replName) {
     List<InterpreterSetting> settings = getInterpreterSettings(noteId);
     InterpreterSetting setting;
     Interpreter interpreter;
@@ -1220,7 +1237,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
       // get default settings (first available)
       // TODO(jl): Fix it in case of returning null
       InterpreterSetting defaultSettings = getDefaultInterpreterSetting(settings);
-      return createOrGetInterpreterList(noteId, defaultSettings).get(0);
+      return createOrGetInterpreterList(user, noteId, defaultSettings).get(0);
     }
 
     String[] replNameSplit = replName.split("\\.");
@@ -1233,7 +1250,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
       setting = getInterpreterSettingByGroup(settings, group);
 
       if (null != setting) {
-        interpreter = getInterpreter(noteId, setting, name);
+        interpreter = getInterpreter(user, noteId, setting, name);
 
         if (null != interpreter) {
           return interpreter;
@@ -1248,7 +1265,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
       // TODO(jl): Handle with noteId to support defaultInterpreter per note.
       setting = getDefaultInterpreterSetting(settings);
 
-      interpreter = getInterpreter(noteId, setting, replName);
+      interpreter = getInterpreter(user, noteId, setting, replName);
 
       if (null != interpreter) {
         return interpreter;
@@ -1259,7 +1276,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
       setting = getInterpreterSettingByGroup(settings, replName);
 
       if (null != setting) {
-        List<Interpreter> interpreters = createOrGetInterpreterList(noteId, setting);
+        List<Interpreter> interpreters = createOrGetInterpreterList(user, noteId, setting);
         if (null != interpreters) {
           return interpreters.get(0);
         }
@@ -1268,7 +1285,7 @@ public class InterpreterFactory implements InterpreterGroupFactory {
       // Support the legacy way to use it
       for (InterpreterSetting s : settings) {
         if (s.getGroup().equals(replName)) {
-          List<Interpreter> interpreters = createOrGetInterpreterList(noteId, s);
+          List<Interpreter> interpreters = createOrGetInterpreterList(user, noteId, s);
           if (null != interpreters) {
             return interpreters.get(0);
           }
@@ -1330,8 +1347,8 @@ public class InterpreterFactory implements InterpreterGroupFactory {
     this.env = env;
   }
 
-  public Map<String, Object> getEditorSetting(String noteId, String replName) {
-    Interpreter intp = getInterpreter(noteId, replName);
+  public Map<String, Object> getEditorSetting(String user, String noteId, String replName) {
+    Interpreter intp = getInterpreter(user, noteId, replName);
     Map<String, Object> editor = Maps.newHashMap(
         ImmutableMap.<String, Object>builder()
             .put("language", "text").build());

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
index d013a88..e5c0f51 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/interpreter/InterpreterOption.java
@@ -17,18 +17,25 @@
 
 package org.apache.zeppelin.interpreter;
 
+import com.google.common.base.Preconditions;
+
 import java.util.List;
 
 /**
  *
  */
 public class InterpreterOption {
+  public static final transient String SHARED = "shared";
+  public static final transient String SCOPED = "scoped";
+  public static final transient String ISOLATED = "isolated";
+
   boolean remote;
   String host = null;
   int port = -1;
-  boolean perNoteSession;
-  boolean perNoteProcess;
-  
+
+  String perNote;
+  String perUser;
+
   boolean isExistingProcess;
   boolean setPermission;
   List<String> users;
@@ -62,11 +69,21 @@ public class InterpreterOption {
   }
 
   public InterpreterOption() {
-    remote = false;
+    this(false);
   }
 
   public InterpreterOption(boolean remote) {
+    this(remote, SHARED, SHARED);
+  }
+
+  public InterpreterOption(boolean remote, String perUser, String perNote) {
+    Preconditions.checkNotNull(remote);
+    Preconditions.checkNotNull(perUser);
+    Preconditions.checkNotNull(perNote);
+
     this.remote = remote;
+    this.perUser = perUser;
+    this.perNote = perNote;
   }
 
   public boolean isRemote() {
@@ -77,14 +94,6 @@ public class InterpreterOption {
     this.remote = remote;
   }
 
-  public boolean isPerNoteSession() {
-    return perNoteSession;
-  }
-
-  public void setPerNoteSession(boolean perNoteSession) {
-    this.perNoteSession = perNoteSession;
-  }
-
   public String getHost() {
     return host;
   }
@@ -93,11 +102,44 @@ public class InterpreterOption {
     return port;
   }
 
-  public boolean isPerNoteProcess() {
-    return perNoteProcess;
+
+  public boolean perUserShared() {
+    return SHARED.equals(perUser);
+  }
+
+  public boolean perUserScoped() {
+    return SCOPED.equals(perUser);
+  }
+
+  public boolean perUserIsolated() {
+    return ISOLATED.equals(perUser);
+  }
+
+  public boolean perNoteShared() {
+    return SHARED.equals(perNote);
+  }
+
+  public boolean perNoteScoped() {
+    return SCOPED.equals(perNote);
+  }
+
+  public boolean perNoteIsolated() {
+    return ISOLATED.equals(perNote);
+  }
+
+  public boolean isProcess() {
+    return perUserIsolated() || perNoteIsolated();
+  }
+
+  public boolean isSession() {
+    return perUserScoped() || perNoteScoped();
+  }
+
+  public void setPerNote(String perNote) {
+    this.perNote = perNote;
   }
 
-  public void setPerNoteProcess(boolean perNoteProcess) {
-    this.perNoteProcess = perNoteProcess;
+  public void setPerUser(String perUser) {
+    this.perUser = perUser;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/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 65f60cd..4611559 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
@@ -24,8 +24,11 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import com.google.gson.annotations.SerializedName;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import org.apache.zeppelin.dep.Dependency;
 
@@ -35,6 +38,7 @@ import static org.apache.zeppelin.notebook.utility.IdHashes.generateId;
  * Interpreter settings
  */
 public class InterpreterSetting {
+  private static final Logger logger = LoggerFactory.getLogger(InterpreterSetting.class);
   private static final String SHARED_PROCESS = "shared_process";
   private String id;
   private String name;
@@ -51,13 +55,19 @@ public class InterpreterSetting {
 
   @Deprecated private transient InterpreterGroupFactory interpreterGroupFactory;
 
-  public InterpreterSetting() {
+  private final transient ReentrantReadWriteLock.ReadLock interpreterGroupReadLock;
+  private final transient ReentrantReadWriteLock.WriteLock interpreterGroupWriteLock;
 
+  public InterpreterSetting() {
+    ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+    interpreterGroupReadLock = lock.readLock();
+    interpreterGroupWriteLock = lock.writeLock();
   }
 
   public InterpreterSetting(String id, String name, String group,
       List<InterpreterInfo> interpreterInfos, Properties properties, List<Dependency> dependencies,
       InterpreterOption option, String path) {
+    this();
     this.id = id;
     this.name = name;
     this.group = group;
@@ -96,40 +106,59 @@ public class InterpreterSetting {
     return group;
   }
 
-  private String getInterpreterProcessKey(String noteId) {
+  private String getInterpreterProcessKey(String user, String noteId) {
+    InterpreterOption option = getOption();
+    String key;
     if (getOption().isExistingProcess) {
-      return Constants.EXISTING_PROCESS;
-    } else if (getOption().isPerNoteProcess()) {
-      return noteId;
+      key = Constants.EXISTING_PROCESS;
+    } else if (getOption().isProcess()) {
+      key = (option.perUserIsolated() ? user : "") + ":" + (option.perNoteIsolated() ? noteId : "");
     } else {
-      return SHARED_PROCESS;
+      key = SHARED_PROCESS;
     }
+
+    logger.debug("getInterpreterProcessKey: {}", key);
+    return key;
   }
 
-  public InterpreterGroup getInterpreterGroup(String noteId) {
-    String key = getInterpreterProcessKey(noteId);
-    synchronized (interpreterGroupRef) {
-      if (!interpreterGroupRef.containsKey(key)) {
-        String interpreterGroupId = getId() + ":" + key;
-        InterpreterGroup intpGroup =
-            interpreterGroupFactory.createInterpreterGroup(interpreterGroupId, getOption());
-        interpreterGroupRef.put(key, intpGroup);
-      }
+  public InterpreterGroup getInterpreterGroup(String user, String noteId) {
+    String key = getInterpreterProcessKey(user, noteId);
+    if (!interpreterGroupRef.containsKey(key)) {
+      String interpreterGroupId = getId() + ":" + key;
+      InterpreterGroup intpGroup =
+          interpreterGroupFactory.createInterpreterGroup(interpreterGroupId, getOption());
+
+      interpreterGroupWriteLock.lock();
+      interpreterGroupRef.put(key, intpGroup);
+      interpreterGroupWriteLock.unlock();
+    }
+    try {
+      interpreterGroupReadLock.lock();
       return interpreterGroupRef.get(key);
+    } finally {
+      interpreterGroupReadLock.unlock();
     }
   }
 
   public Collection<InterpreterGroup> getAllInterpreterGroups() {
-    synchronized (interpreterGroupRef) {
+    try {
+      interpreterGroupReadLock.lock();
       return new LinkedList<>(interpreterGroupRef.values());
+    } finally {
+      interpreterGroupReadLock.unlock();
     }
   }
 
   void closeAndRemoveInterpreterGroup(String noteId) {
-    String key = getInterpreterProcessKey(noteId);
-    InterpreterGroup groupToRemove;
-    synchronized (interpreterGroupRef) {
-      groupToRemove = interpreterGroupRef.remove(key);
+    String key = getInterpreterProcessKey("", noteId);
+
+    InterpreterGroup groupToRemove = null;
+    for (String intpKey : new HashSet<>(interpreterGroupRef.keySet())) {
+      if (intpKey.contains(key)) {
+        interpreterGroupWriteLock.lock();
+        groupToRemove = interpreterGroupRef.remove(intpKey);
+        interpreterGroupWriteLock.unlock();
+      }
     }
 
     if (groupToRemove != null) {
@@ -139,11 +168,9 @@ public class InterpreterSetting {
   }
 
   void closeAndRmoveAllInterpreterGroups() {
-    synchronized (interpreterGroupRef) {
-      HashSet<String> groupsToRemove = new HashSet<>(interpreterGroupRef.keySet());
-      for (String key : groupsToRemove) {
-        closeAndRemoveInterpreterGroup(key);
-      }
+    HashSet<String> groupsToRemove = new HashSet<>(interpreterGroupRef.keySet());
+    for (String key : groupsToRemove) {
+      closeAndRemoveInterpreterGroup(key);
     }
   }
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/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 1281e71..7ad2697 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
@@ -30,6 +30,7 @@ import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import com.google.common.base.Preconditions;
 import com.google.gson.Gson;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
@@ -286,8 +287,8 @@ public class Note implements Serializable, ParagraphJobListener {
    * @param paragraphId ID of paragraph
    * @return a paragraph that was deleted, or <code>null</code> otherwise
    */
-  public Paragraph removeParagraph(String paragraphId) {
-    removeAllAngularObjectInParagraph(paragraphId);
+  public Paragraph removeParagraph(String user, String paragraphId) {
+    removeAllAngularObjectInParagraph(user, paragraphId);
     ResourcePoolUtils.removeResourcesBelongsToParagraph(getId(), paragraphId);
     synchronized (paragraphs) {
       Iterator<Paragraph> i = paragraphs.iterator();
@@ -350,8 +351,8 @@ public class Note implements Serializable, ParagraphJobListener {
 
       if (index < 0 || index >= paragraphs.size()) {
         if (throwWhenIndexIsOutOfBound) {
-          throw new IndexOutOfBoundsException(
-              "paragraph size is " + paragraphs.size() + " , index is " + index);
+          throw new IndexOutOfBoundsException("paragraph size is " + paragraphs.size() +
+              " , index is " + index);
         } else {
           return;
         }
@@ -437,6 +438,8 @@ public class Note implements Serializable, ParagraphJobListener {
     }
     if (p.getStatus().isRunning()) {
       info.put("progress", String.valueOf(p.progress()));
+    } else {
+      info.put("progress", String.valueOf(100));
     }
     return info;
   }
@@ -460,6 +463,9 @@ public class Note implements Serializable, ParagraphJobListener {
    */
   public void runAll() {
     String cronExecutingUser = (String) getConfig().get("cronExecutingUser");
+    if (null == cronExecutingUser) {
+      cronExecutingUser = "anonymous";
+    }
     synchronized (paragraphs) {
       for (Paragraph p : paragraphs) {
         if (!p.isEnabled()) {
@@ -482,7 +488,8 @@ public class Note implements Serializable, ParagraphJobListener {
     Paragraph p = getParagraph(paragraphId);
     p.setListener(jobListenerFactory.getParagraphJobListener(this));
     String requiredReplName = p.getRequiredReplName();
-    Interpreter intp = factory.getInterpreter(getId(), requiredReplName);
+    Interpreter intp = factory.getInterpreter(p.getUser(), getId(), requiredReplName);
+
     if (intp == null) {
       String intpExceptionMsg =
           p.getJobName() + "'s Interpreter " + requiredReplName + " not found";
@@ -494,6 +501,7 @@ public class Note implements Serializable, ParagraphJobListener {
       throw intpException;
     }
     if (p.getConfig().get("enabled") == null || (Boolean) p.getConfig().get("enabled")) {
+      p.setAuthenticationInfo(p.getAuthenticationInfo());
       intp.getScheduler().submit(p);
     }
   }
@@ -526,7 +534,7 @@ public class Note implements Serializable, ParagraphJobListener {
     }
   }
 
-  private void snapshotAngularObjectRegistry() {
+  private void snapshotAngularObjectRegistry(String user) {
     angularObjects = new HashMap<>();
 
     List<InterpreterSetting> settings = factory.getInterpreterSettings(getId());
@@ -535,13 +543,13 @@ public class Note implements Serializable, ParagraphJobListener {
     }
 
     for (InterpreterSetting setting : settings) {
-      InterpreterGroup intpGroup = setting.getInterpreterGroup(id);
+      InterpreterGroup intpGroup = setting.getInterpreterGroup(user, id);
       AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry();
       angularObjects.put(intpGroup.getId(), registry.getAllWithGlobal(id));
     }
   }
 
-  private void removeAllAngularObjectInParagraph(String paragraphId) {
+  private void removeAllAngularObjectInParagraph(String user, String paragraphId) {
     angularObjects = new HashMap<>();
 
     List<InterpreterSetting> settings = factory.getInterpreterSettings(getId());
@@ -550,7 +558,7 @@ public class Note implements Serializable, ParagraphJobListener {
     }
 
     for (InterpreterSetting setting : settings) {
-      InterpreterGroup intpGroup = setting.getInterpreterGroup(id);
+      InterpreterGroup intpGroup = setting.getInterpreterGroup(user, id);
       AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry();
 
       if (registry instanceof RemoteAngularObjectRegistry) {
@@ -580,8 +588,9 @@ public class Note implements Serializable, ParagraphJobListener {
   }
 
   public void persist(AuthenticationInfo subject) throws IOException {
+    Preconditions.checkNotNull(subject, "AuthenticationInfo should not be null");
     stopDelayedPersistTimer();
-    snapshotAngularObjectRegistry();
+    snapshotAngularObjectRegistry(subject.getUser());
     index.updateIndexDoc(this);
     repo.save(this, subject);
   }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/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 1e65a86..d996488 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
@@ -31,6 +31,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+
+import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Sets;
@@ -135,6 +137,7 @@ public class Notebook implements NoteEventListener {
    * @throws IOException
    */
   public Note createNote(AuthenticationInfo subject) throws IOException {
+    Preconditions.checkNotNull(subject, "AuthenticationInfo should not be null");
     Note note;
     if (conf.getBoolean(ConfVars.ZEPPELIN_NOTEBOOK_AUTO_INTERPRETER_BINDING)) {
       note = createNote(replFactory.getDefaultInterpreterSettingList(), subject);
@@ -158,7 +161,7 @@ public class Notebook implements NoteEventListener {
       notes.put(note.getId(), note);
     }
     if (interpreterIds != null) {
-      bindInterpretersToNote(note.getId(), interpreterIds);
+      bindInterpretersToNote(subject.getUser(), note.getId(), interpreterIds);
     }
 
     if (subject != null && !"anonymous".equals(subject.getUser())) {
@@ -252,7 +255,7 @@ public class Notebook implements NoteEventListener {
     }
     // Copy the interpreter bindings
     List<String> boundInterpreterSettingsIds = getBindedInterpreterSettingsIds(sourceNote.getId());
-    bindInterpretersToNote(newNote.getId(), boundInterpreterSettingsIds);
+    bindInterpretersToNote(subject.getUser(), newNote.getId(), boundInterpreterSettingsIds);
 
     List<Paragraph> paragraphs = sourceNote.getParagraphs();
     for (Paragraph p : paragraphs) {
@@ -264,7 +267,7 @@ public class Notebook implements NoteEventListener {
     return newNote;
   }
 
-  public void bindInterpretersToNote(String id, List<String> interpreterSettingIds)
+  public void bindInterpretersToNote(String user, String id, List<String> interpreterSettingIds)
       throws IOException {
     Note note = getNote(id);
     if (note != null) {
@@ -275,7 +278,7 @@ public class Notebook implements NoteEventListener {
         }
       }
 
-      replFactory.setInterpreters(note.getId(), interpreterSettingIds);
+      replFactory.setInterpreters(user, note.getId(), interpreterSettingIds);
       // comment out while note.getNoteReplLoader().setInterpreters(...) do the same
       // replFactory.putNoteInterpreterSettingBinding(id, interpreterSettingIds);
     }
@@ -306,18 +309,21 @@ public class Notebook implements NoteEventListener {
   }
 
   public void removeNote(String id, AuthenticationInfo subject) {
+    Preconditions.checkNotNull(subject, "AuthenticationInfo should not be null");
+
     Note note;
 
     synchronized (notes) {
       note = notes.remove(id);
     }
-    replFactory.removeNoteInterpreterSettingBinding(id);
+    replFactory.removeNoteInterpreterSettingBinding(subject.getUser(), id);
     notebookIndex.deleteIndexDocs(note);
     notebookAuthorization.removeNote(id);
 
     // remove from all interpreter instance's angular object registry
     for (InterpreterSetting settings : replFactory.get()) {
-      AngularObjectRegistry registry = settings.getInterpreterGroup(id).getAngularObjectRegistry();
+      AngularObjectRegistry registry =
+          settings.getInterpreterGroup(subject.getUser(), id).getAngularObjectRegistry();
       if (registry instanceof RemoteAngularObjectRegistry) {
         // remove paragraph scope object
         for (Paragraph p : note.getParagraphs()) {
@@ -437,7 +443,7 @@ public class Notebook implements NoteEventListener {
       SnapshotAngularObject snapshot = angularObjectSnapshot.get(name);
       List<InterpreterSetting> settings = replFactory.get();
       for (InterpreterSetting setting : settings) {
-        InterpreterGroup intpGroup = setting.getInterpreterGroup(note.getId());
+        InterpreterGroup intpGroup = setting.getInterpreterGroup(subject.getUser(), note.getId());
         if (intpGroup.getId().equals(snapshot.getIntpGroupId())) {
           AngularObjectRegistry registry = intpGroup.getAngularObjectRegistry();
           String noteId = snapshot.getAngularObject().getNoteId();
@@ -533,7 +539,7 @@ public class Notebook implements NoteEventListener {
       return noteList;
     }
   }
-  
+
   public List<Note> getAllNotes(AuthenticationInfo subject) {
     final Set<String> entities = Sets.newHashSet();
     if (subject != null) {

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
index 7807abb..955ba2d 100644
--- a/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
+++ b/zeppelin-zengine/src/main/java/org/apache/zeppelin/notebook/Paragraph.java
@@ -105,6 +105,10 @@ public class Paragraph extends Job implements Serializable, Cloneable {
            + new Random(System.currentTimeMillis()).nextInt();
   }
 
+  public String getUser() {
+    return user;
+  }
+
   public String getText() {
     return text;
   }
@@ -193,7 +197,7 @@ public class Paragraph extends Job implements Serializable, Cloneable {
   }
 
   public Interpreter getRepl(String name) {
-    return factory.getInterpreter(note.getId(), name);
+    return factory.getInterpreter(user, note.getId(), name);
   }
 
   public Interpreter getCurrentRepl() {
@@ -442,8 +446,8 @@ public class Paragraph extends Job implements Serializable, Cloneable {
 
     if (!factory.getInterpreterSettings(note.getId()).isEmpty()) {
       InterpreterSetting intpGroup = factory.getInterpreterSettings(note.getId()).get(0);
-      registry = intpGroup.getInterpreterGroup(note.getId()).getAngularObjectRegistry();
-      resourcePool = intpGroup.getInterpreterGroup(note.getId()).getResourcePool();
+      registry = intpGroup.getInterpreterGroup(getUser(), note.getId()).getAngularObjectRegistry();
+      resourcePool = intpGroup.getInterpreterGroup(getUser(), note.getId()).getResourcePool();
     }
 
     List<InterpreterContextRunner> runners = new LinkedList<InterpreterContextRunner>();
@@ -582,6 +586,7 @@ public class Paragraph extends Job implements Serializable, Cloneable {
   }
 
   private boolean isValidInterpreter(String replName) {
-    return factory.getInterpreter(note.getId(), replName) != null;
+    return factory.getInterpreter("",
+        note.getId(), replName) != null;
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java
index 29cdf55..294817c 100644
--- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java
+++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/helium/HeliumApplicationFactoryTest.java
@@ -27,6 +27,8 @@ import org.apache.zeppelin.notebook.repo.VFSNotebookRepo;
 import org.apache.zeppelin.scheduler.Job;
 import org.apache.zeppelin.scheduler.SchedulerFactory;
 import org.apache.zeppelin.search.SearchService;
+import org.apache.zeppelin.user.AuthenticationInfo;
+import org.apache.zeppelin.user.Credentials;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -50,6 +52,7 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
   private VFSNotebookRepo notebookRepo;
   private Notebook notebook;
   private HeliumApplicationFactory heliumAppFactory;
+  private AuthenticationInfo anonymous;
 
   @Before
   public void setUp() throws Exception {
@@ -82,7 +85,7 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
     heliumAppFactory = new HeliumApplicationFactory();
     depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo");
     factory = new InterpreterFactory(conf,
-        new InterpreterOption(true), null, null, heliumAppFactory, depResolver);
+        new InterpreterOption(true), null, null, heliumAppFactory, depResolver, false);
     HashMap<String, String> env = new HashMap<String, String>();
     env.put("ZEPPELIN_CLASSPATH", new File("./target/test-classes").getAbsolutePath());
     factory.setEnv(env);
@@ -98,11 +101,13 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
         this,
         search,
         notebookAuthorization,
-        null);
+        new Credentials(false, null));
 
     heliumAppFactory.setNotebook(notebook);
 
     notebook.addNotebookEventListener(heliumAppFactory);
+
+    anonymous = new AuthenticationInfo("anonymous");
   }
 
   @After
@@ -131,13 +136,14 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
         HeliumTestApplication.class.getName(),
         new String[][]{});
 
-    Note note1 = notebook.createNote(null);
-    factory.setInterpreters(note1.getId(),factory.getDefaultInterpreterSettingList());
+    Note note1 = notebook.createNote(anonymous);
+    factory.setInterpreters("user", note1.getId(),factory.getDefaultInterpreterSettingList());
 
     Paragraph p1 = note1.addParagraph();
 
     // make sure interpreter process running
     p1.setText("%mock1 job");
+    p1.setAuthenticationInfo(anonymous);
     note1.run(p1.getId());
     while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield();
 
@@ -162,7 +168,7 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
 
     // clean
     heliumAppFactory.unload(p1, appId);
-    notebook.removeNote(note1.getId(), null);
+    notebook.removeNote(note1.getId(), anonymous);
   }
 
   @Test
@@ -175,13 +181,14 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
         HeliumTestApplication.class.getName(),
         new String[][]{});
 
-    Note note1 = notebook.createNote(null);
-    factory.setInterpreters(note1.getId(), factory.getDefaultInterpreterSettingList());
+    Note note1 = notebook.createNote(anonymous);
+    factory.setInterpreters("user", note1.getId(), factory.getDefaultInterpreterSettingList());
 
     Paragraph p1 = note1.addParagraph();
 
     // make sure interpreter process running
     p1.setText("%mock1 job");
+    p1.setAuthenticationInfo(anonymous);
     note1.run(p1.getId());
     while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield();
 
@@ -193,13 +200,13 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
     }
 
     // when remove paragraph
-    note1.removeParagraph(p1.getId());
+    note1.removeParagraph("user", p1.getId());
 
     // then
     assertEquals(ApplicationState.Status.UNLOADED, app.getStatus());
 
     // clean
-    notebook.removeNote(note1.getId(), null);
+    notebook.removeNote(note1.getId(), anonymous);
   }
 
 
@@ -213,13 +220,14 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
         HeliumTestApplication.class.getName(),
         new String[][]{});
 
-    Note note1 = notebook.createNote(null);
-    notebook.bindInterpretersToNote(note1.getId(), factory.getDefaultInterpreterSettingList());
+    Note note1 = notebook.createNote(anonymous);
+    notebook.bindInterpretersToNote("user", note1.getId(), factory.getDefaultInterpreterSettingList());
 
     Paragraph p1 = note1.addParagraph();
 
     // make sure interpreter process running
     p1.setText("%mock1 job");
+    p1.setAuthenticationInfo(anonymous);
     note1.run(p1.getId());
     while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield();
 
@@ -231,19 +239,19 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
     }
 
     // when unbind interpreter
-    notebook.bindInterpretersToNote(note1.getId(), new LinkedList<String>());
+    notebook.bindInterpretersToNote("user", note1.getId(), new LinkedList<String>());
 
     // then
     assertEquals(ApplicationState.Status.UNLOADED, app.getStatus());
 
     // clean
-    notebook.removeNote(note1.getId(), null);
+    notebook.removeNote(note1.getId(), anonymous);
   }
 
   @Test
   public void testInterpreterUnbindOfNullReplParagraph() throws IOException {
     // create note
-    Note note1 = notebook.createNote(null);
+    Note note1 = notebook.createNote(anonymous);
 
     // add paragraph with invalid magic
     Paragraph p1 = note1.addParagraph();
@@ -255,10 +263,10 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
 
     // Unbind all interpreter from note
     // NullPointerException shouldn't occur here
-    notebook.bindInterpretersToNote(note1.getId(), new LinkedList<String>());
+    notebook.bindInterpretersToNote("user", note1.getId(), new LinkedList<String>());
 
     // remove note
-    notebook.removeNote(note1.getId(), null);
+    notebook.removeNote(note1.getId(), anonymous);
   }
 
 
@@ -272,8 +280,8 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
         HeliumTestApplication.class.getName(),
         new String[][]{});
 
-    Note note1 = notebook.createNote(null);
-    notebook.bindInterpretersToNote(note1.getId(), factory.getDefaultInterpreterSettingList());
+    Note note1 = notebook.createNote(anonymous);
+    notebook.bindInterpretersToNote("user", note1.getId(), factory.getDefaultInterpreterSettingList());
     String mock1IntpSettingId = null;
     for (InterpreterSetting setting : notebook.getBindedInterpreterSettings(note1.getId())) {
       if (setting.getName().equals("mock1")) {
@@ -286,6 +294,7 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
 
     // make sure interpreter process running
     p1.setText("%mock1 job");
+    p1.setAuthenticationInfo(anonymous);
     note1.run(p1.getId());
     while(p1.isTerminated()==false || p1.getResult()==null) Thread.yield();
     assertEquals(0, p1.getAllApplicationStates().size());
@@ -307,7 +316,7 @@ public class HeliumApplicationFactoryTest implements JobListenerFactory {
     assertEquals(ApplicationState.Status.UNLOADED, app.getStatus());
 
     // clean
-    notebook.removeNote(note1.getId(), null);
+    notebook.removeNote(note1.getId(), anonymous);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/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 09031a5..a2a799a 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
@@ -33,6 +33,8 @@ 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.apache.zeppelin.notebook.repo.zeppelinhub.security.Authentication;
+import org.apache.zeppelin.user.AuthenticationInfo;
 import org.apache.zeppelin.interpreter.remote.RemoteInterpreter;
 import org.apache.zeppelin.notebook.JobListenerFactory;
 import org.apache.zeppelin.notebook.Note;
@@ -87,7 +89,7 @@ public class InterpreterFactoryTest {
     conf = new ZeppelinConfiguration();
     schedulerFactory = new SchedulerFactory();
     depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo");
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver);
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false);
     context = new InterpreterContext("note", "id", "title", "text", null, null, null, null, null, null, null);
 
     SearchService search = mock(SearchService.class);
@@ -114,8 +116,8 @@ public class InterpreterFactoryTest {
 
 //    mock1Setting = factory.createNewSetting("mock11", "mock1", new ArrayList<Dependency>(), new InterpreterOption(false), new Properties());
 
-    InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("sharedProcess");
-    factory.createInterpretersForNote(mock1Setting, "sharedProcess", "session");
+    InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("user", "sharedProcess");
+    factory.createInterpretersForNote(mock1Setting, "user", "sharedProcess", "session");
 
     // get interpreter
     assertNotNull("get Interpreter", interpreterGroup.get("session").get(0));
@@ -125,12 +127,12 @@ public class InterpreterFactoryTest {
 
     // restart interpreter
     factory.restart(mock1Setting.getId());
-    assertNull(mock1Setting.getInterpreterGroup("sharedProcess").get("session"));
+    assertNull(mock1Setting.getInterpreterGroup("user", "sharedProcess").get("session"));
   }
 
   @Test
   public void testRemoteRepl() throws Exception {
-    factory = new InterpreterFactory(conf, new InterpreterOption(true), null, null, null, depResolver);
+    factory = new InterpreterFactory(conf, new InterpreterOption(true), null, null, null, depResolver, false);
     List<InterpreterSetting> all = factory.get();
     InterpreterSetting mock1Setting = null;
     for (InterpreterSetting setting : all) {
@@ -139,8 +141,8 @@ public class InterpreterFactoryTest {
         break;
       }
     }
-    InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("sharedProcess");
-    factory.createInterpretersForNote(mock1Setting, "sharedProcess", "session");
+    InterpreterGroup interpreterGroup = mock1Setting.getInterpreterGroup("user", "sharedProcess");
+    factory.createInterpretersForNote(mock1Setting, "user", "sharedProcess", "session");
     // get interpreter
     assertNotNull("get Interpreter", interpreterGroup.get("session").get(0));
     assertTrue(interpreterGroup.get("session").get(0) instanceof LazyOpenInterpreter);
@@ -186,13 +188,13 @@ public class InterpreterFactoryTest {
     factory.createNewSetting("new-mock1", "mock1", new LinkedList<Dependency>(), new InterpreterOption(false), new Properties());
     assertEquals(numInterpreters + 1, factory.get().size());
 
-    InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, null, depResolver);
+    InterpreterFactory factory2 = new InterpreterFactory(conf, null, null, null, depResolver, false);
     assertEquals(numInterpreters + 1, factory2.get().size());
   }
 
   @Test
   public void testInterpreterAliases() throws IOException, RepositoryException {
-    factory = new InterpreterFactory(conf, null, null, null, depResolver);
+    factory = new InterpreterFactory(conf, null, null, null, depResolver, false);
     final InterpreterInfo info1 = new InterpreterInfo("className1", "name1", true, null);
     final InterpreterInfo info2 = new InterpreterInfo("className2", "name1", true, null);
     factory.add("group1", new ArrayList<InterpreterInfo>(){{
@@ -205,16 +207,39 @@ public class InterpreterFactoryTest {
     final InterpreterSetting setting1 = factory.createNewSetting("test-group1", "group1", new ArrayList<Dependency>(), new InterpreterOption(true), new Properties());
     final InterpreterSetting setting2 = factory.createNewSetting("test-group2", "group1", new ArrayList<Dependency>(), new InterpreterOption(true), new Properties());
 
-    factory.setInterpreters("note", new ArrayList<String>() {{
+    factory.setInterpreters("user", "note", new ArrayList<String>() {{
       add(setting1.getId());
       add(setting2.getId());
     }});
 
-    assertEquals("className1", factory.getInterpreter("note", "test-group1").getClassName());
-    assertEquals("className1", factory.getInterpreter("note", "group1").getClassName());
+    assertEquals("className1", factory.getInterpreter("user1", "note", "test-group1").getClassName());
+    assertEquals("className1", factory.getInterpreter("user1", "note", "group1").getClassName());
   }
 
   @Test
+  public void testMultiUser() throws IOException, RepositoryException {
+    factory = new InterpreterFactory(conf, null, null, null, depResolver, true);
+    final InterpreterInfo info1 = new InterpreterInfo("className1", "name1", true, null);
+    factory.add("group1", new ArrayList<InterpreterInfo>(){{
+      add(info1);
+    }}, new ArrayList<Dependency>(), new InterpreterOption(true), new Properties(), "/path1");
+
+    InterpreterOption perUserInterpreterOption = new InterpreterOption(true, InterpreterOption.ISOLATED, InterpreterOption.SHARED);
+    final InterpreterSetting setting1 = factory.createNewSetting("test-group1", "group1", new ArrayList<Dependency>(), perUserInterpreterOption, new Properties());
+
+    factory.setInterpreters("user1", "note", new ArrayList<String>() {{
+      add(setting1.getId());
+    }});
+
+    factory.setInterpreters("user2", "note", new ArrayList<String>() {{
+      add(setting1.getId());
+    }});
+
+    assertNotEquals(factory.getInterpreter("user1", "note", "test-group1"), factory.getInterpreter("user2", "note", "test-group1"));
+  }
+
+
+  @Test
   public void testInvalidInterpreterSettingName() {
     try {
       factory.createNewSetting("new.mock1", "mock1", new LinkedList<Dependency>(), new InterpreterOption(false), new Properties());
@@ -233,19 +258,19 @@ public class InterpreterFactoryTest {
         intpIds.add(intpSetting.getId());
       }
     }
-    Note note = notebook.createNote(intpIds, null);
+    Note note = notebook.createNote(intpIds, new AuthenticationInfo("anonymous"));
 
     // get editor setting from interpreter-setting.json
-    Map<String, Object> editor = factory.getEditorSetting(note.getId(), "mock11");
+    Map<String, Object> editor = factory.getEditorSetting("user1", note.getId(), "mock11");
     assertEquals("java", editor.get("language"));
 
     // when interpreter is not loaded via interpreter-setting.json
     // or editor setting doesn't exit
-    editor = factory.getEditorSetting(note.getId(), "mock1");
+    editor = factory.getEditorSetting("user1", note.getId(), "mock1");
     assertEquals(null, editor.get("language"));
 
     // when interpreter is not bound to note
-    editor = factory.getEditorSetting(note.getId(), "mock2");
+    editor = factory.getEditorSetting("user1", note.getId(), "mock2");
     assertEquals("text", editor.get("language"));
   }
 }

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/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 2450899..d19ceae 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
@@ -60,7 +60,7 @@ public class NoteInterpreterLoaderTest {
     MockInterpreter2.register("mock2", "group2", "org.apache.zeppelin.interpreter.mock.MockInterpreter2");
 
     depResolver = new DependencyResolver(tmpDir.getAbsolutePath() + "/local-repo");
-    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver);
+    factory = new InterpreterFactory(conf, new InterpreterOption(false), null, null, null, depResolver, false);
   }
 
   @After
@@ -71,92 +71,92 @@ public class NoteInterpreterLoaderTest {
 
   @Test
   public void testGetInterpreter() throws IOException {
-    factory.setInterpreters("note", factory.getDefaultInterpreterSettingList());
+    factory.setInterpreters("user", "note", factory.getDefaultInterpreterSettingList());
 
     // when there're no interpreter selection directive
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", null).getClassName());
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", "").getClassName());
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", " ").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", null).getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", "").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", " ").getClassName());
 
     // when group name is omitted
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("note", "mock11").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("user", "note", "mock11").getClassName());
 
     // when 'name' is ommitted
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", "group1").getClassName());
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("note", "group2").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", "group1").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("user", "note", "group2").getClassName());
 
     // when nothing is ommitted
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("note", "group1.mock1").getClassName());
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("note", "group1.mock11").getClassName());
-    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("note", "group2.mock2").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter1", factory.getInterpreter("user", "note", "group1.mock1").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter11", factory.getInterpreter("user", "note", "group1.mock11").getClassName());
+    assertEquals("org.apache.zeppelin.interpreter.mock.MockInterpreter2", factory.getInterpreter("user", "note", "group2.mock2").getClassName());
 
-    factory.closeNote("note");
+    factory.closeNote("user", "note");
   }
 
   @Test
   public void testNoteSession() throws IOException {
-    factory.setInterpreters("noteA", factory.getDefaultInterpreterSettingList());
-    factory.getInterpreterSettings("noteA").get(0).getOption().setPerNoteSession(true);
+    factory.setInterpreters("user", "noteA", factory.getDefaultInterpreterSettingList());
+    factory.getInterpreterSettings("noteA").get(0).getOption().setPerNote(InterpreterOption.SCOPED);
 
-    factory.setInterpreters("noteB", factory.getDefaultInterpreterSettingList());
-    factory.getInterpreterSettings("noteB").get(0).getOption().setPerNoteSession(true);
+    factory.setInterpreters("user", "noteB", factory.getDefaultInterpreterSettingList());
+    factory.getInterpreterSettings("noteB").get(0).getOption().setPerNote(InterpreterOption.SCOPED);
 
     // interpreters are not created before accessing it
-    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("shared_process").get("noteA"));
-    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("shared_process").get("noteB"));
+    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA"));
+    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB"));
 
-    factory.getInterpreter("noteA", null).open();
-    factory.getInterpreter("noteB", null).open();
+    factory.getInterpreter("user", "noteA", null).open();
+    factory.getInterpreter("user", "noteB", null).open();
 
     assertTrue(
-        factory.getInterpreter("noteA", null).getInterpreterGroup().getId().equals(
-        factory.getInterpreter("noteB", null).getInterpreterGroup().getId()));
+        factory.getInterpreter("user", "noteA", null).getInterpreterGroup().getId().equals(
+        factory.getInterpreter("user", "noteB", null).getInterpreterGroup().getId()));
 
     // interpreters are created after accessing it
-    assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("shared_process").get("noteA"));
-    assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("shared_process").get("noteB"));
+    assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA"));
+    assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB"));
 
     // when
-    factory.closeNote("noteA");
-    factory.closeNote("noteB");
+    factory.closeNote("user", "noteA");
+    factory.closeNote("user", "noteB");
 
     // interpreters are destroyed after close
-    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("shared_process").get("noteA"));
-    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("shared_process").get("noteB"));
+    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "shared_process").get("noteA"));
+    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "shared_process").get("noteB"));
 
   }
 
   @Test
   public void testNotePerInterpreterProcess() throws IOException {
-    factory.setInterpreters("noteA", factory.getDefaultInterpreterSettingList());
-    factory.getInterpreterSettings("noteA").get(0).getOption().setPerNoteProcess(true);
+    factory.setInterpreters("user", "noteA", factory.getDefaultInterpreterSettingList());
+    factory.getInterpreterSettings("noteA").get(0).getOption().setPerNote(InterpreterOption.ISOLATED);
 
-    factory.setInterpreters("noteB", factory.getDefaultInterpreterSettingList());
-    factory.getInterpreterSettings("noteB").get(0).getOption().setPerNoteProcess(true);
+    factory.setInterpreters("user", "noteB", factory.getDefaultInterpreterSettingList());
+    factory.getInterpreterSettings("noteB").get(0).getOption().setPerNote(InterpreterOption.ISOLATED);
 
     // interpreters are not created before accessing it
-    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("noteA").get("noteA"));
-    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("noteB").get("noteB"));
+    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA"));
+    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB"));
 
-    factory.getInterpreter("noteA", null).open();
-    factory.getInterpreter("noteB", null).open();
+    factory.getInterpreter("user", "noteA", null).open();
+    factory.getInterpreter("user", "noteB", null).open();
 
     // per note interpreter process
     assertFalse(
-        factory.getInterpreter("noteA", null).getInterpreterGroup().getId().equals(
-        factory.getInterpreter("noteB", null).getInterpreterGroup().getId()));
+        factory.getInterpreter("user", "noteA", null).getInterpreterGroup().getId().equals(
+        factory.getInterpreter("user", "noteB", null).getInterpreterGroup().getId()));
 
     // interpreters are created after accessing it
-    assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("noteA").get("noteA"));
-    assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("noteB").get("noteB"));
+    assertNotNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA"));
+    assertNotNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB"));
 
     // when
-    factory.closeNote("noteA");
-    factory.closeNote("noteB");
+    factory.closeNote("user", "noteA");
+    factory.closeNote("user", "noteB");
 
     // interpreters are destroyed after close
-    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("noteA").get("noteA"));
-    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("noteB").get("noteB"));
+    assertNull(factory.getInterpreterSettings("noteA").get(0).getInterpreterGroup("user", "noteA").get("noteA"));
+    assertNull(factory.getInterpreterSettings("noteB").get(0).getInterpreterGroup("user", "noteB").get("noteB"));
   }
 
 

http://git-wip-us.apache.org/repos/asf/zeppelin/blob/908b2a74/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java
----------------------------------------------------------------------
diff --git a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java
index a44bfad..a077274 100644
--- a/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java
+++ b/zeppelin-zengine/src/test/java/org/apache/zeppelin/notebook/NoteTest.java
@@ -22,6 +22,7 @@ import org.apache.zeppelin.interpreter.InterpreterFactory;
 import org.apache.zeppelin.notebook.repo.NotebookRepo;
 import org.apache.zeppelin.scheduler.Scheduler;
 import org.apache.zeppelin.search.SearchService;
+import org.apache.zeppelin.user.AuthenticationInfo;
 import org.apache.zeppelin.user.Credentials;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -58,9 +59,11 @@ public class NoteTest {
   @Mock
   InterpreterFactory interpreterFactory;
 
+  private AuthenticationInfo anonymous = new AuthenticationInfo("anonymous");
+
   @Test
   public void runNormalTest() {
-    when(interpreterFactory.getInterpreter(anyString(), eq("spark"))).thenReturn(interpreter);
+    when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("spark"))).thenReturn(interpreter);
     when(interpreter.getScheduler()).thenReturn(scheduler);
 
     String pText = "%spark sc.version";
@@ -68,11 +71,12 @@ public class NoteTest {
 
     Paragraph p = note.addParagraph();
     p.setText(pText);
+    p.setAuthenticationInfo(anonymous);
     note.run(p.getId());
 
     ArgumentCaptor<Paragraph> pCaptor = ArgumentCaptor.forClass(Paragraph.class);
     verify(scheduler, only()).submit(pCaptor.capture());
-    verify(interpreterFactory, only()).getInterpreter(anyString(), eq("spark"));
+    verify(interpreterFactory, only()).getInterpreter(anyString(), anyString(), eq("spark"));
 
     assertEquals("Paragraph text", pText, pCaptor.getValue().getText());
   }
@@ -87,7 +91,7 @@ public class NoteTest {
 
   @Test
   public void addParagraphWithLastReplNameTest() {
-    when(interpreterFactory.getInterpreter(anyString(), eq("spark"))).thenReturn(interpreter);
+    when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("spark"))).thenReturn(interpreter);
 
     Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener);
     Paragraph p1 = note.addParagraph();
@@ -99,7 +103,7 @@ public class NoteTest {
 
   @Test
   public void insertParagraphWithLastReplNameTest() {
-    when(interpreterFactory.getInterpreter(anyString(), eq("spark"))).thenReturn(interpreter);
+    when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("spark"))).thenReturn(interpreter);
 
     Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener);
     Paragraph p1 = note.addParagraph();
@@ -111,7 +115,7 @@ public class NoteTest {
 
   @Test
   public void insertParagraphWithInvalidReplNameTest() {
-    when(interpreterFactory.getInterpreter(anyString(), eq("invalid"))).thenReturn(null);
+    when(interpreterFactory.getInterpreter(anyString(), anyString(), eq("invalid"))).thenReturn(null);
 
     Note note = new Note(repo, interpreterFactory, jobListenerFactory, index, credentials, noteEventListener);
     Paragraph p1 = note.addParagraph();


Mime
View raw message