Merge branch 'master' into workflow

# Conflicts:
#	spark/src/main/java/org/apache/zeppelin/spark/SparkInterpreter.java
This commit is contained in:
CloverHearts 2016-11-15 20:04:39 +09:00
commit afb9db7465
81 changed files with 3367 additions and 611 deletions

3
.gitignore vendored
View file

@ -52,6 +52,9 @@ zeppelin-web/bower_components
.Rhistory
/R/
# scio
.bigquery/
# project level
/logs/
/run/

318
README.md
View file

@ -17,323 +17,13 @@ Core feature:
To know more about Zeppelin, visit our web site [http://zeppelin.apache.org](http://zeppelin.apache.org)
## Requirements
* Git
* Java 1.7
* Tested on Mac OSX, Ubuntu 14.X, CentOS 6.X, Windows 7 Pro SP1
* Maven (if you want to build from the source code)
* Node.js Package Manager (npm, downloaded by Maven during build phase)
## Getting Started
### Before Build
If you don't have requirements prepared, install it.
(The installation method may vary according to your environment, example is for Ubuntu.)
### Install binary package
Please go to [install](http://zeppelin.apache.org/docs/snapshot/install/install.html) to install Apache Zeppelin from binary package.
```
sudo apt-get update
sudo apt-get install git
sudo apt-get install openjdk-7-jdk
sudo apt-get install npm
sudo apt-get install libfontconfig
```
### Build from source
Please check [Build from source](http://zeppelin.apache.org/docs/snapshot/install/build.html) to build Zeppelin from source.
#### Proxy settings (optional)
First of all, set your proxy configuration on Maven `settings.xml`.
```
<settings>
<proxies>
<proxy>
<id>proxy-http</id>
<active>true</active>
<protocol>http</protocol>
<host>localhost</host>
<port>3128</port>
<!-- <username>usr</username>
<password>pwd</password> -->
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
<proxy>
<id>proxy-https</id>
<active>true</active>
<protocol>https</protocol>
<host>localhost</host>
<port>3128</port>
<!-- <username>usr</username>
<password>pwd</password> -->
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
</proxies>
</settings>
```
Then, run these commands from shell.
```
npm config set proxy http://localhost:3128
npm config set https-proxy http://localhost:3128
npm config set registry "http://registry.npmjs.org/"
npm config set strict-ssl false
git config --global http.proxy http://localhost:3128
git config --global https.proxy http://localhost:3128
git config --global url."http://".insteadOf git://
```
Cleanup: set `active false` in Maven `settings.xml` and run these commands.
```
npm config rm proxy
npm config rm https-proxy
git config --global --unset http.proxy
git config --global --unset https.proxy
git config --global --unset url."http://".insteadOf
```
_Notes:_
- If you are behind NTLM proxy you can use [Cntlm Authentication Proxy](http://cntlm.sourceforge.net/).
- Replace `localhost:3128` with the standard pattern `http://user:pwd@host:port`.
#### Install maven
```
wget http://www.eu.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
sudo tar -zxf apache-maven-3.3.9-bin.tar.gz -C /usr/local/
sudo ln -s /usr/local/apache-maven-3.3.9/bin/mvn /usr/local/bin/mvn
```
_Notes:_
- Ensure node is installed by running `node --version`
- Ensure maven is running version 3.1.x or higher with `mvn -version`
- Configure maven to use more memory than usual by `export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=1024m"`
### Build
If you want to build Zeppelin from the source, please first clone this repository, then:
```
mvn clean package -DskipTests [Options]
```
Each Interpreter requires different Options.
#### Spark Interpreter
To build with a specific Spark version, Hadoop version or specific features, define one or more of the following profiles and options:
##### `-Pspark-[version]`
Set spark major version
Available profiles are
```
-Pspark-2.0
-Pspark-1.6
-Pspark-1.5
-Pspark-1.4
-Pcassandra-spark-1.5
-Pcassandra-spark-1.4
-Pcassandra-spark-1.3
-Pcassandra-spark-1.2
-Pcassandra-spark-1.1
```
minor version can be adjusted by `-Dspark.version=x.x.x`
##### `-Phadoop-[version]`
set hadoop major version
Available profiles are
```
-Phadoop-0.23
-Phadoop-1
-Phadoop-2.2
-Phadoop-2.3
-Phadoop-2.4
-Phadoop-2.6
```
minor version can be adjusted by `-Dhadoop.version=x.x.x`
##### `-Pscala-[version] (optional)`
set scala version (default 2.10)
Available profiles are
```
-Pscala-2.10
-Pscala-2.11
```
##### `-Pyarn` (optional)
enable YARN support for local mode
> YARN for local mode is not supported for Spark v1.5.0 or higher. Set `SPARK_HOME` instead.
##### `-Ppyspark` (optional)
enable [PySpark](http://spark.apache.org/docs/latest/api/python/) support for local mode.
##### `-Pr` (optional)
enable [R](https://www.r-project.org/) support with [SparkR](https://spark.apache.org/docs/latest/sparkr.html) integration.
##### `-Psparkr` (optional)
another [R](https://www.r-project.org/) support with [SparkR](https://spark.apache.org/docs/latest/sparkr.html) integration as well as local mode support.
##### `-Pvendor-repo` (optional)
enable 3rd party vendor repository (cloudera)
##### `-Pmapr[version]` (optional)
For the MapR Hadoop Distribution, these profiles will handle the Hadoop version. As MapR allows different versions of Spark to be installed, you should specify which version of Spark is installed on the cluster by adding a Spark profile (`-Pspark-1.6`, `-Pspark-2.0`, etc.) as needed.
The correct Maven artifacts can be found for every version of MapR at http://doc.mapr.com
Available profiles are
```
-Pmapr3
-Pmapr40
-Pmapr41
-Pmapr50
-Pmapr51
```
#### -Pexamples (optional)
Bulid examples under zeppelin-examples directory
#### Example
Here're some examples:
```sh
# build with spark-2.0, scala-2.11
./dev/change_scala_version.sh 2.11
mvn clean package -Pspark-2.0 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pscala-2.11
# build with spark-1.6, scala-2.10
mvn clean package -Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr
# spark-cassandra integration
mvn clean package -Pcassandra-spark-1.5 -Dhadoop.version=2.6.0 -Phadoop-2.6 -DskipTests
# with CDH
mvn clean package -Pspark-1.5 -Dhadoop.version=2.6.0-cdh5.5.0 -Phadoop-2.6 -Pvendor-repo -DskipTests
# with MapR
mvn clean package -Pspark-1.5 -Pmapr50 -DskipTests
```
#### Ignite Interpreter
```sh
mvn clean package -Dignite.version=1.6.0 -DskipTests
```
#### Scalding Interpreter
```sh
mvn clean package -Pscalding -DskipTests
```
### Configure
If you wish to configure Zeppelin option (like port number), configure the following files:
```
./conf/zeppelin-env.sh
./conf/zeppelin-site.xml
```
(You can copy `./conf/zeppelin-env.sh.template` into `./conf/zeppelin-env.sh`.
Same for `zeppelin-site.xml`.)
#### Setting SPARK_HOME and HADOOP_HOME
Without `SPARK_HOME` and `HADOOP_HOME`, Zeppelin uses embedded Spark and Hadoop binaries that you have specified with mvn build option.
If you want to use system provided Spark and Hadoop, export `SPARK_HOME` and `HADOOP_HOME` in `zeppelin-env.sh`.
You can use any supported version of spark without rebuilding Zeppelin.
```sh
# ./conf/zeppelin-env.sh
export SPARK_HOME=...
export HADOOP_HOME=...
```
#### External cluster configuration
Mesos
```sh
# ./conf/zeppelin-env.sh
export MASTER=mesos://...
export ZEPPELIN_JAVA_OPTS="-Dspark.executor.uri=/path/to/spark-*.tgz" or SPARK_HOME="/path/to/spark_home"
export MESOS_NATIVE_LIBRARY=/path/to/libmesos.so
```
If you set `SPARK_HOME`, you should deploy spark binary on the same location to all worker nodes. And if you set `spark.executor.uri`, every worker can read that file on its node.
Yarn
```sh
# ./conf/zeppelin-env.sh
export SPARK_HOME=/path/to/spark_dir
```
### Run
```sh
./bin/zeppelin-daemon.sh start
```
And browse [localhost:8080](localhost:8080) in your browser.
For configuration details check __`./conf`__ subdirectory.
### Building for Scala 2.11
To produce a Zeppelin package compiled with Scala 2.11, use the -Pscala-2.11 profile:
```
./dev/change_scala_version.sh 2.11
mvn clean package -Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Pscala-2.11 -DskipTests clean install
```
### Package
To package the final distribution including the compressed archive, run:
```sh
mvn clean package -Pbuild-distr
```
To build a distribution with specific profiles, run:
```sh
mvn clean package -Pbuild-distr -Pspark-1.5 -Phadoop-2.4 -Pyarn -Ppyspark
```
The profiles `-Pspark-1.5 -Phadoop-2.4 -Pyarn -Ppyspark` can be adjusted if you wish to build to a specific spark versions, or omit support such as `yarn`.
The archive is generated under _`zeppelin-distribution/target`_ directory
###Run end-to-end tests
Zeppelin comes with a set of end-to-end acceptance tests driving headless selenium browser
```sh
# assumes zeppelin-server running on localhost:8080 (use -Durl=.. to override)
mvn verify
# or take care of starting/stoping zeppelin-server from packaged zeppelin-distribuion/target
mvn verify -P using-packaged-distr
```
[![Analytics](https://ga-beacon.appspot.com/UA-45176241-4/apache/zeppelin/README.md?pixel)](https://github.com/igrigorik/ga-beacon)

View file

@ -102,7 +102,13 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-scio_${scala.binary.version}</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
@ -175,34 +181,6 @@
<artifactId>beam-runners-direct-java</artifactId>
<version>${beam.beam.version}</version>
</dependency>
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-runners-flink_2.10</artifactId>
<version>${beam.beam.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
<exclusion>
<artifactId>netty-all</artifactId>
<groupId>io.netty</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.beam</groupId>
<artifactId>beam-runners-flink_2.10-examples</artifactId>
<version>${beam.beam.version}</version>
<exclusions>
<exclusion>
<artifactId>slf4j-log4j12</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>

View file

@ -9,5 +9,27 @@
"editor": {
"editOnDblClick": false
}
},
{
"group": "beam",
"name": "scio",
"className": "org.apache.zeppelin.scio.ScioInterpreter",
"properties": {
"zeppelin.scio.argz": {
"envName": "ZEPPELIN_SCIO_ARGZ",
"propertyName": "zeppelin.scio.argz",
"defaultValue": "--runner=InProcessPipelineRunner",
"description": "Scio interpreter wide arguments"
},
"zeppelin.scio.maxResult": {
"envName": "ZEPPELIN_SCIO_MAXRESULT",
"propertyName": "zeppelin.scio.maxResult",
"defaultValue": "1000",
"description": "Max number of SCollection results to display."
}
},
"editor": {
"language": "scala"
}
}
]

View file

@ -35,4 +35,5 @@ md org.apache.zeppelin:zeppelin-markdown:0.6.1 Markdown
pig org.apache.zeppelin:zeppelin-pig:0.6.1 Pig interpreter
postgresql org.apache.zeppelin:zeppelin-postgresql:0.6.1 Postgresql interpreter
python org.apache.zeppelin:zeppelin-python:0.6.1 Python interpreter
scio org.apache.zeppelin:zeppelin-scio:0.6.1 Scio interpreter
shell org.apache.zeppelin:zeppelin-shell:0.6.1 Shell command

View file

@ -190,7 +190,7 @@
<property>
<name>zeppelin.interpreters</name>
<value>org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,,org.apache.zeppelin.python.PythonInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.postgresql.PostgreSqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter,org.apache.zeppelin.bigquery.BigQueryInterpreter,org.apache.zeppelin.beam.BeamInterpreter,org.apache.zeppelin.pig.PigInterpreter, org.apache.zeppelin.pig.PigQueryInterpreter</value>
<value>org.apache.zeppelin.spark.SparkInterpreter,org.apache.zeppelin.spark.PySparkInterpreter,org.apache.zeppelin.rinterpreter.RRepl,org.apache.zeppelin.rinterpreter.KnitR,org.apache.zeppelin.spark.SparkRInterpreter,org.apache.zeppelin.spark.SparkSqlInterpreter,org.apache.zeppelin.spark.DepInterpreter,org.apache.zeppelin.markdown.Markdown,org.apache.zeppelin.angular.AngularInterpreter,org.apache.zeppelin.shell.ShellInterpreter,org.apache.zeppelin.file.HDFSFileInterpreter,org.apache.zeppelin.flink.FlinkInterpreter,,org.apache.zeppelin.python.PythonInterpreter,org.apache.zeppelin.lens.LensInterpreter,org.apache.zeppelin.ignite.IgniteInterpreter,org.apache.zeppelin.ignite.IgniteSqlInterpreter,org.apache.zeppelin.cassandra.CassandraInterpreter,org.apache.zeppelin.geode.GeodeOqlInterpreter,org.apache.zeppelin.postgresql.PostgreSqlInterpreter,org.apache.zeppelin.jdbc.JDBCInterpreter,org.apache.zeppelin.kylin.KylinInterpreter,org.apache.zeppelin.elasticsearch.ElasticsearchInterpreter,org.apache.zeppelin.scalding.ScaldingInterpreter,org.apache.zeppelin.alluxio.AlluxioInterpreter,org.apache.zeppelin.hbase.HbaseInterpreter,org.apache.zeppelin.livy.LivySparkInterpreter,org.apache.zeppelin.livy.LivyPySparkInterpreter,org.apache.zeppelin.livy.LivySparkRInterpreter,org.apache.zeppelin.livy.LivySparkSQLInterpreter,org.apache.zeppelin.bigquery.BigQueryInterpreter,org.apache.zeppelin.beam.BeamInterpreter,org.apache.zeppelin.pig.PigInterpreter,org.apache.zeppelin.pig.PigQueryInterpreter,org.apache.zeppelin.scio.ScioInterpreter</value>
<description>Comma separated interpreter configurations. First interpreter become a default</description>
</property>

View file

@ -33,6 +33,7 @@
<li role="separator" class="divider"></li>
<li class="title"><span><b>More</b><span></li>
<li><a href="{{BASE_PATH}}/install/upgrade.html">Upgrade Zeppelin Version</a></li>
<li><a href="{{BASE_PATH}}/install/build.html">Build from source</a></li>
<li><a href="{{BASE_PATH}}/quickstart/install_with_flink_and_spark_cluster.html">Install Zeppelin with Flink and Spark Clusters Tutorial</a></li>
</ul>
</li>
@ -59,6 +60,7 @@
<li><a href="{{BASE_PATH}}/interpreter/hive.html">Hive</a></li>
<li><a href="{{BASE_PATH}}/interpreter/ignite.html">Ignite</a></li>
<li><a href="{{BASE_PATH}}/interpreter/jdbc.html">JDBC</a></li>
<li><a href="{{BASE_PATH}}/interpreter/kylin.html">Kylin</a></li>
<li><a href="{{BASE_PATH}}/interpreter/lens.html">Lens</a></li>
<li><a href="{{BASE_PATH}}/interpreter/livy.html">Livy</a></li>
<li><a href="{{BASE_PATH}}/interpreter/markdown.html">Markdown</a></li>
@ -67,6 +69,7 @@
<li><a href="{{BASE_PATH}}/interpreter/postgresql.html">Postgresql, HAWQ</a></li>
<li><a href="{{BASE_PATH}}/interpreter/r.html">R</a></li>
<li><a href="{{BASE_PATH}}/interpreter/scalding.html">Scalding</a></li>
<li><a href="{{BASE_PATH}}/interpreter/scio.html">Scio</a></li>
<li><a href="{{BASE_PATH}}/interpreter/shell.html">Shell</a></li>
<li><a href="{{BASE_PATH}}/interpreter/spark.html">Spark</a></li>
</ul>
@ -100,8 +103,7 @@
<li><a href="{{BASE_PATH}}/rest-api/rest-credential.html">Credential API</a></li>
<li role="separator" class="divider"></li>
<li class="title"><span><b>Security</b><span></li>
<li><a href="{{BASE_PATH}}/security/authentication.html">Authentication for NGINX</a></li>
<li><a href="{{BASE_PATH}}/security/shiroauthentication.html">Shiro Authentication</a></li>
<li><a href="{{BASE_PATH}}/security/shiroauthentication.html">Shiro Authentication</a></li>
<li><a href="{{BASE_PATH}}/security/notebook_authorization.html">Notebook Authorization</a></li>
<li><a href="{{BASE_PATH}}/security/datasource_authorization.html">Data Source Authorization</a></li>
<li role="separator" class="divider"></li>

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

View file

@ -134,6 +134,7 @@ Join to our [Mailing list](https://zeppelin.apache.org/community.html) and repor
* [Customize Zeppelin Homepage](./manual/notebookashomepage.html) with one of your notebooks
* More
* [Upgrade Apache Zeppelin Version](./install/upgrade.html): a manual procedure of upgrading Apache Zeppelin version
* [Build](./install/build.html): Build from source
####Interpreter

343
docs/install/build.md Normal file
View file

@ -0,0 +1,343 @@
---
layout: page
title: "Build from Source"
description: "How to build Zeppelin from source"
group: install
---
<!--
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.
-->
{% include JB/setup %}
## Building from Source
<div id="toc"></div>
If you want to build from source, you must first install the following dependencies:
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Git</td>
<td>(Any Version)</td>
</tr>
<tr>
<td>Maven</td>
<td>3.1.x or higher</td>
</tr>
<tr>
<td>JDK</td>
<td>1.7</td>
</tr>
</table>
If you haven't installed Git and Maven yet, check the [Build requirements](#build-requirements) section and follow the step by step instructions from there.
####1. Clone the Apache Zeppelin repository
```
git clone https://github.com/apache/zeppelin.git
```
####2. Build source
You can build Zeppelin with following maven command:
```
mvn clean package -DskipTests [Options]
```
If you're unsure about the options, use the same commands that creates official binary package.
```bash
# update all pom.xml to use scala 2.11
./dev/change_scala_version.sh 2.11
# build zeppelin with all interpreters and include latest version of Apache spark support for local mode.
mvn clean package -DskipTests -Pspark-2.0 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pr -Pscala-2.11
```
####3. Done
You can directly start Zeppelin by running after successful build:
```bash
./bin/zeppelin-daemon.sh start
```
Check [build-profiles](#build-profiles) section for further build options.
If you are behind proxy, follow instructions in [Proxy setting](#proxy-setting-optional) section.
If you're interested in contribution, please check [Contributing to Apache Zeppelin (Code)](../development/howtocontribute.html) and [Contributing to Apache Zeppelin (Website)](../../development/contributewebsite.html).
### Build profiles
#### Spark Interpreter
To build with a specific Spark version, Hadoop version or specific features, define one or more of the following profiles and options:
##### `-Pspark-[version]`
Set spark major version
Available profiles are
```
-Pspark-2.0
-Pspark-1.6
-Pspark-1.5
-Pspark-1.4
-Pcassandra-spark-1.5
-Pcassandra-spark-1.4
-Pcassandra-spark-1.3
-Pcassandra-spark-1.2
-Pcassandra-spark-1.1
```
minor version can be adjusted by `-Dspark.version=x.x.x`
##### `-Phadoop-[version]`
set hadoop major version
Available profiles are
```
-Phadoop-0.23
-Phadoop-1
-Phadoop-2.2
-Phadoop-2.3
-Phadoop-2.4
-Phadoop-2.6
```
minor version can be adjusted by `-Dhadoop.version=x.x.x`
##### `-Pscala-[version] (optional)`
set scala version (default 2.10)
Available profiles are
```
-Pscala-2.10
-Pscala-2.11
```
##### `-Pyarn` (optional)
enable YARN support for local mode
> YARN for local mode is not supported for Spark v1.5.0 or higher. Set `SPARK_HOME` instead.
##### `-Ppyspark` (optional)
enable [PySpark](http://spark.apache.org/docs/latest/api/python/) support for local mode.
##### `-Pr` (optional)
enable [R](https://www.r-project.org/) support with [SparkR](https://spark.apache.org/docs/latest/sparkr.html) integration.
##### `-Psparkr` (optional)
another [R](https://www.r-project.org/) support with [SparkR](https://spark.apache.org/docs/latest/sparkr.html) integration as well as local mode support.
##### `-Pvendor-repo` (optional)
enable 3rd party vendor repository (cloudera)
##### `-Pmapr[version]` (optional)
For the MapR Hadoop Distribution, these profiles will handle the Hadoop version. As MapR allows different versions of Spark to be installed, you should specify which version of Spark is installed on the cluster by adding a Spark profile (`-Pspark-1.6`, `-Pspark-2.0`, etc.) as needed.
The correct Maven artifacts can be found for every version of MapR at http://doc.mapr.com
Available profiles are
```
-Pmapr3
-Pmapr40
-Pmapr41
-Pmapr50
-Pmapr51
```
#### -Pexamples (optional)
Bulid examples under zeppelin-examples directory
### Build command examples
Here are some examples with several options:
```bash
# build with spark-2.0, scala-2.11
./dev/change_scala_version.sh 2.11
mvn clean package -Pspark-2.0 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pscala-2.11 -DskipTests
# build with spark-1.6, scala-2.10
mvn clean package -Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -DskipTests
# spark-cassandra integration
mvn clean package -Pcassandra-spark-1.5 -Dhadoop.version=2.6.0 -Phadoop-2.6 -DskipTests -DskipTests
# with CDH
mvn clean package -Pspark-1.5 -Dhadoop.version=2.6.0-cdh5.5.0 -Phadoop-2.6 -Pvendor-repo -DskipTests
# with MapR
mvn clean package -Pspark-1.5 -Pmapr50 -DskipTests
```
Ignite Interpreter
```bash
mvn clean package -Dignite.version=1.6.0 -DskipTests
```
Scalding Interpreter
```bash
mvn clean package -Pscalding -DskipTests
```
## Build requirements
### Install requirements
If you don't have requirements prepared, install it.
(The installation method may vary according to your environment, example is for Ubuntu.)
```
sudo apt-get update
sudo apt-get install git
sudo apt-get install openjdk-7-jdk
sudo apt-get install npm
sudo apt-get install libfontconfig
```
### Install maven
```
wget http://www.eu.apache.org/dist/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz
sudo tar -zxf apache-maven-3.3.9-bin.tar.gz -C /usr/local/
sudo ln -s /usr/local/apache-maven-3.3.9/bin/mvn /usr/local/bin/mvn
```
_Notes:_
- Ensure node is installed by running `node --version`
- Ensure maven is running version 3.1.x or higher with `mvn -version`
- Configure maven to use more memory than usual by `export MAVEN_OPTS="-Xmx2g -XX:MaxPermSize=1024m"`
## Proxy setting (optional)
If you're behind the proxy, you'll need to configure maven and npm to pass through it.
First of all, configure maven in your `~/.m2/settings.xml`.
```
<settings>
<proxies>
<proxy>
<id>proxy-http</id>
<active>true</active>
<protocol>http</protocol>
<host>localhost</host>
<port>3128</port>
<!-- <username>usr</username>
<password>pwd</password> -->
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
<proxy>
<id>proxy-https</id>
<active>true</active>
<protocol>https</protocol>
<host>localhost</host>
<port>3128</port>
<!-- <username>usr</username>
<password>pwd</password> -->
<nonProxyHosts>localhost|127.0.0.1</nonProxyHosts>
</proxy>
</proxies>
</settings>
```
Then, next commands will configure npm.
```
npm config set proxy http://localhost:3128
npm config set https-proxy http://localhost:3128
npm config set registry "http://registry.npmjs.org/"
npm config set strict-ssl false
```
Configure git as well
```
git config --global http.proxy http://localhost:3128
git config --global https.proxy http://localhost:3128
git config --global url."http://".insteadOf git://
```
To clean up, set `active false` in Maven `settings.xml` and run these commands.
```bash
npm config rm proxy
npm config rm https-proxy
git config --global --unset http.proxy
git config --global --unset https.proxy
git config --global --unset url."http://".insteadOf
```
_Notes:_
- If you are behind NTLM proxy you can use [Cntlm Authentication Proxy](http://cntlm.sourceforge.net/).
- Replace `localhost:3128` with the standard pattern `http://user:pwd@host:port`.
## Package
To package the final distribution including the compressed archive, run:
```sh
mvn clean package -Pbuild-distr
```
To build a distribution with specific profiles, run:
```sh
mvn clean package -Pbuild-distr -Pspark-1.5 -Phadoop-2.4 -Pyarn -Ppyspark
```
The profiles `-Pspark-1.5 -Phadoop-2.4 -Pyarn -Ppyspark` can be adjusted if you wish to build to a specific spark versions, or omit support such as `yarn`.
The archive is generated under _`zeppelin-distribution/target`_ directory
## Run end-to-end tests
Zeppelin comes with a set of end-to-end acceptance tests driving headless selenium browser
```sh
# assumes zeppelin-server running on localhost:8080 (use -Durl=.. to override)
mvn verify
# or take care of starting/stoping zeppelin-server from packaged zeppelin-distribuion/target
mvn verify -P using-packaged-distr
```
[![Analytics](https://ga-beacon.appspot.com/UA-45176241-4/apache/zeppelin/README.md?pixel)](https://github.com/igrigorik/ga-beacon)

View file

@ -44,86 +44,28 @@ Apache Zeppelin officially supports and is tested on the following environments:
</tr>
</table>
To install Apache Zeppelin, you have two options:
* You can [download pre-built binary packages](#downloading-binary-package) from the archive. This is usually easier than building from source, and you can download the latest stable version (or older versions, if necessary).
* You can also [build from source](#building-from-source). This gives you a development version of Zeppelin, which is more unstable but has new features.
### Downloading Binary Package
Stable binary packages are available on the [Apache Zeppelin Download Page](http://zeppelin.apache.org/download.html). You can download a default package with all interpreters, or you can download the *net-install* package, which lets you choose which interpreters to install.
Two binary packages are available on the [Apache Zeppelin Download Page](http://zeppelin.apache.org/download.html). Only difference between these two binaries is interpreters are included in the package file.
If you downloaded the default package, just unpack it in a directory of your choice and you're ready to go. If you downloaded the *net-install* package, you should manually [install additional interpreters](../manual/interpreterinstallation.html) first. You can also install everything by running `./bin/install-interpreter.sh --all`.
- #### Package with `all` interpreters.
After unpacking, jump to the [Starting Apache Zeppelin from Command Line](#starting-apache-zeppelin-from-the-command-line).
Just unpack it in a directory of your choice and you're ready to go.
### Building from Source
- #### Package with `net-install` interpreters.
If you want to build from source, you must first install the following dependencies:
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>Git</td>
<td>(Any Version)</td>
</tr>
<tr>
<td>Maven</td>
<td>3.1.x or higher</td>
</tr>
</table>
If you haven't installed Git and Maven yet, check the [Before Build](https://github.com/apache/zeppelin/blob/master/README.md#before-build) section and follow the step by step instructions from there.
####1. Clone the Apache Zeppelin repository
```
git clone https://github.com/apache/zeppelin.git
```
####2. Build source with options
Each interpreter requires different build options. For more information about build options, please see the [Build](https://github.com/apache/zeppelin#build) section.
```
mvn clean package -DskipTests [Options]
```
Here are some examples with several options:
```
# build with spark-2.0, scala-2.11
./dev/change_scala_version.sh 2.11
mvn clean package -Pspark-2.0 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr -Pscala-2.11
# build with spark-1.6, scala-2.10
mvn clean package -Pspark-1.6 -Phadoop-2.4 -Pyarn -Ppyspark -Psparkr
# spark-cassandra integration
mvn clean package -Pcassandra-spark-1.5 -Dhadoop.version=2.6.0 -Phadoop-2.6 -DskipTests
# with CDH
mvn clean package -Pspark-1.5 -Dhadoop.version=2.6.0-cdh5.5.0 -Phadoop-2.6 -Pvendor-repo -DskipTests
# with MapR
mvn clean package -Pspark-1.5 -Pmapr50 -DskipTests
```
For further information about building from source, please see [README.md](https://github.com/apache/zeppelin/blob/master/README.md) in the Zeppelin repository.
Unpack and follow [install additional interpreters](../manual/interpreterinstallation.html) to install interpreters. If you're unsure, just run `./bin/install-interpreter.sh --all` and install all interpreters.
## Starting Apache Zeppelin from the Command Line
#### Starting Apache Zeppelin
On all platforms except for Windows:
On all unix like platforms:
```
bin/zeppelin-daemon.sh start
```
If you are using Windows:
If you are on Windows:
```
bin\zeppelin.cmd
@ -137,63 +79,36 @@ After Zeppelin has started successfully, go to [http://localhost:8080](http://lo
bin/zeppelin-daemon.sh stop
```
#### (Optional) Start Apache Zeppelin with a service manager
> **Note :** The below description was written based on Ubuntu Linux.
Apache Zeppelin can be auto-started as a service with an init script, using a service manager like **upstart**.
This is an example upstart script saved as `/etc/init/zeppelin.conf`
This allows the service to be managed with commands such as
```
sudo service zeppelin start
sudo service zeppelin stop
sudo service zeppelin restart
```
Other service managers could use a similar approach with the `upstart` argument passed to the `zeppelin-daemon.sh` script.
```
bin/zeppelin-daemon.sh upstart
```
**zeppelin.conf**
```
description "zeppelin"
start on (local-filesystems and net-device-up IFACE!=lo)
stop on shutdown
# Respawn the process on unexpected termination
respawn
# respawn the job up to 7 times within a 5 second period.
# If the job exceeds these values, it will be stopped and marked as failed.
respawn limit 7 5
# zeppelin was installed in /usr/share/zeppelin in this example
chdir /usr/share/zeppelin
exec bin/zeppelin-daemon.sh upstart
```
## Next Steps
Congratulations, you have successfully installed Apache Zeppelin! Here are two next steps you might find useful:
Congratulations, you have successfully installed Apache Zeppelin! Here are few steps you might find useful:
#### If you are new to Apache Zeppelin...
* For an in-depth overview of the Apache Zeppelin UI, head to [Explore Apache Zeppelin UI](../quickstart/explorezeppelinui.html).
* After getting familiar with the Apache Zeppelin UI, have fun with a short walk-through [Tutorial](../quickstart/tutorial.html) that uses the Apache Spark backend.
* If you need more configuration for Apache Zeppelin, jump to the next section: [Apache Zeppelin Configuration](#apache-zeppelin-configuration).
#### New to Apache Zeppelin...
* For an in-depth overview, head to [Explore Apache Zeppelin UI](../quickstart/explorezeppelinui.html).
* And then, try run [tutorial](http://localhost:8080/#/notebook/2A94M5J1Z) notebook in your Zeppelin.
* And see how to change [configurations](#apache-zeppelin-configuration) like port number, etc.
#### If you need more information about Spark or JDBC interpreter settings...
* Apache Zeppelin provides deep integration with [Apache Spark](http://spark.apache.org/). For more information, see [Spark Interpreter for Apache Zeppelin](../interpreter/spark.html).
* You can also use generic JDBC connections in Apache Zeppelin. Go to [Generic JDBC Interpreter for Apache Zeppelin](../interpreter/jdbc.html).
#### If you are in a multi-user environment...
* You can set permissions for your notebooks and secure data resource in a multi-user environment. Go to **More** -> **Security** section.
#### Zeppelin with Apache Spark ...
* To know more about deep integration with [Apache Spark](http://spark.apache.org/), check [Spark Interpreter](../interpreter/spark.html).
#### Zeppelin with JDBC data sources ...
* Check [JDBC Interpreter](../interpreter/jdbc.html) to know more about configure and uses multiple JDBC data sources.
#### Zeppelin with Python ...
* Check [Python interpreter](../interpreter/python.html) to know more about Matplotlib, Pandas integration.
#### Multi-user environment ...
* Turn on [authentication](../security/shiroauthentication.html).
* Manage your [notebook permission](../security/notebook_authorization.html).
* For more informations, go to **More** -> **Security** section.
#### Other useful informations ...
* Learn how [Display System](../displaysystem/basicdisplaysystem.html) works.
* Use [Service Manager](#start-apache-zeppelin-with-a-service-manager) to start Zeppelin.
* If you're using previous version please see [Upgrade Zeppelin version](./upgrade.html).
## Apache Zeppelin Configuration
You can configure Apache Zeppelin with either **environment variables** in `conf/zeppelin-env.sh` (`conf\zeppelin-env.cmd` for Windows) or **Java properties** in `conf/zeppelin-site.xml`. If both are defined, then the **environment variables** will take priority.
@ -416,3 +331,50 @@ You can configure Apache Zeppelin with either **environment variables** in `conf
<td>Size (in characters) of the maximum text message that can be received by websocket.</td>
</tr>
</table>
#### Start Apache Zeppelin with a service manager
> **Note :** The below description was written based on Ubuntu Linux.
Apache Zeppelin can be auto-started as a service with an init script, using a service manager like **upstart**.
This is an example upstart script saved as `/etc/init/zeppelin.conf`
This allows the service to be managed with commands such as
```
sudo service zeppelin start
sudo service zeppelin stop
sudo service zeppelin restart
```
Other service managers could use a similar approach with the `upstart` argument passed to the `zeppelin-daemon.sh` script.
```
bin/zeppelin-daemon.sh upstart
```
**zeppelin.conf**
```
description "zeppelin"
start on (local-filesystems and net-device-up IFACE!=lo)
stop on shutdown
# Respawn the process on unexpected termination
respawn
# respawn the job up to 7 times within a 5 second period.
# If the job exceeds these values, it will be stopped and marked as failed.
respawn limit 7 5
# zeppelin was installed in /usr/share/zeppelin in this example
chdir /usr/share/zeppelin
exec bin/zeppelin-daemon.sh upstart
```
## Building from Source
If you want to build from source instead of using binary package, follow the instructions [here](./build.html).

View file

@ -33,8 +33,8 @@ You can use Zeppelin to retrieve distributed data from cache using Ignite SQL in
## Installing and Running Ignite example
In order to use Ignite interpreters, you may install Apache Ignite in some simple steps:
1. Download Ignite [source release](https://ignite.apache.org/download.html#sources) or [binary release](https://ignite.apache.org/download.html#binaries) whatever you want. But you must download Ignite as the same version of Zeppelin's. If it is not, you can't use scala code on Zeppelin. You can find ignite version in Zeppelin at the pom.xml which is placed under `path/to/your-Zeppelin/ignite/pom.xml` ( Of course, in Zeppelin source release ). Please check `ignite.version` .<br>Currently, Zeppelin provides ignite only in Zeppelin source release. So, if you download Zeppelin binary release( `zeppelin-0.5.0-incubating-bin-spark-xxx-hadoop-xx` ), you can not use ignite interpreter on Zeppelin. We are planning to include ignite in a future binary release.
2. Examples are shipped as a separate Maven project, so to start running you simply need to import provided <dest_dir>/apache-ignite-fabric-1.2.0-incubating-bin/pom.xml file into your favourite IDE, such as Eclipse.
1. Ignite provides examples only with source or binary release. Download Ignite [source release](https://ignite.apache.org/download.html#sources) or [binary release](https://ignite.apache.org/download.html#binaries) whatever you want. But you must download Ignite as the same version of Zeppelin's. If it is not, you can't use scala code on Zeppelin. The supported Ignite version is specified in [Supported Interpreter table](https://zeppelin.apache.org/supported_interpreters.html#ignite) for each Zeppelin release. If you're using Zeppelin master branch, please see `ignite.version` in `path/to/your-Zeppelin/ignite/pom.xml`.
2. Examples are shipped as a separate Maven project, so to start running you simply need to import provided `<dest_dir>/apache-ignite-fabric-{version}-bin/examples/pom.xml` file into your favourite IDE, such as Eclipse.
* In case of Eclipse, Eclipse -> File -> Import -> Existing Maven Projects
* Set examples directory path to Eclipse and select the pom.xml.
@ -58,12 +58,12 @@ At the "Interpreters" menu, you may edit Ignite interpreter or create new one. Z
<tr>
<td>ignite.addresses</td>
<td>127.0.0.1:47500..47509</td>
<td>Coma separated list of Ignite cluster hosts. See [Ignite Cluster Configuration](https://apacheignite.readme.io/v1.2/docs/cluster-config) section for more details.</td>
<td>Coma separated list of Ignite cluster hosts. See [Ignite Cluster Configuration](https://apacheignite.readme.io/docs/cluster-config) section for more details.</td>
</tr>
<tr>
<td>ignite.clientMode</td>
<td>true</td>
<td>You can connect to the Ignite cluster as client or server node. See [Ignite Clients vs. Servers](https://apacheignite.readme.io/v1.2/docs/clients-vs-servers) section for details. Use true or false values in order to connect in client or server mode respectively.</td>
<td>You can connect to the Ignite cluster as client or server node. See [Ignite Clients vs. Servers](https://apacheignite.readme.io/docs/clients-vs-servers) section for details. Use true or false values in order to connect in client or server mode respectively.</td>
</tr>
<tr>
<td>ignite.config.url</td>
@ -78,7 +78,7 @@ At the "Interpreters" menu, you may edit Ignite interpreter or create new one. Z
<tr>
<td>ignite.peerClassLoadingEnabled</td>
<td>true</td>
<td>Enables peer-class-loading. See [Zero Deployment](https://apacheignite.readme.io/v1.2/docs/zero-deployment) section for details. Use true or false values in order to enable or disable P2P class loading respectively.</td>
<td>Enables peer-class-loading. See [Zero Deployment](https://apacheignite.readme.io/docs/zero-deployment) section for details. Use true or false values in order to enable or disable P2P class loading respectively.</td>
</tr>
</table>
@ -89,7 +89,7 @@ After configuring Ignite interpreter, create your own notebook. Then you can bin
![Binding Interpreters](../assets/themes/zeppelin/img/docs-img/ignite-interpreter-binding.png)
For more interpreter binding information see [here](http://zeppelin.apache.org/docs/manual/interpreters.html).
For more interpreter binding information see [here](../manual/interpreters.html#what-is-interpreter-setting).
### Ignite SQL interpreter
In order to execute SQL query, use ` %ignite.ignitesql ` prefix. <br>

View file

@ -50,7 +50,7 @@ JDBC interpreter lets you create a JDBC connection to any data sources seamlessl
</li>
<li style="padding-bottom: 5px; list-style: circle">
<a href="https://hive.apache.org/" target="_blank">Apache Hive</a> -
<a href="https://cwiki.apache.org/confluence/display/Hive/HiveClient#HiveClient-JDBC" target="_blank">JDBC Driver</a>
<a href="https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC" target="_blank">JDBC Driver</a>
</li>
<li style="padding-bottom: 5px; list-style: circle">
<a href="https://phoenix.apache.org/" target="_blank">Apache Phoenix</a> itself is a JDBC driver
@ -125,7 +125,7 @@ The last step is **Dependency Setting**. Since Zeppelin only includes `PostgreSQ
<img src="../assets/themes/zeppelin/img/docs-img/edit_dependencies.png" width="600px" />
That's it. You can find more JDBC connection setting examples([Mysql](#mysql), [Apache Hive](#apache-hive), [Apache Phoenix](#apache-phoenix), and [Apache Tajo](#apache-tajo)) in [this section](#examples).
That's it. You can find more JDBC connection setting examples([Mysql](#mysql), [MariaDB](#mariadb), [Redshift](#redshift), [Apache Hive](#apache-hive), [Apache Phoenix](#apache-phoenix), and [Apache Tajo](#apache-tajo)) in [this section](#examples).
## More properties
There are more JDBC interpreter properties you can specify like below.
@ -205,6 +205,50 @@ WHERE name='{{"{{performer=Sheryl Crow|Doof|Fanfarlo|Los Paranoia"}}}}'
## Examples
Here are some examples you can refer to. Including the below connectors, you can connect every databases as long as it can be configured with it's JDBC driver.
### Postgres
<img src="../assets/themes/zeppelin/img/docs-img/postgres_setting.png" width="600px" />
##### Properties
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>default.driver</td>
<td>org.postgresql.Driver</td>
</tr>
<tr>
<td>default.url</td>
<td>jdbc:postgresql://localhost:5432/</td>
</tr>
<tr>
<td>default.user</td>
<td>mysql_user</td>
</tr>
<tr>
<td>default.password</td>
<td>mysql_password</td>
</tr>
</table>
[Postgres JDBC Driver Docs](https://jdbc.postgresql.org/documentation/documentation.html)
##### Dependencies
<table class="table-configuration">
<tr>
<th>Artifact</th>
<th>Excludes</th>
</tr>
<tr>
<td>org.postgresql:postgresql:9.4.1211</td>
<td></td>
</tr>
</table>
[Maven Repository: org.postgresql:postgresql](https://mvnrepository.com/artifact/org.postgresql/postgresql)
### Mysql
<img src="../assets/themes/zeppelin/img/docs-img/mysql_setting.png" width="600px" />
@ -233,6 +277,8 @@ Here are some examples you can refer to. Including the below connectors, you can
</tr>
</table>
[Mysql JDBC Driver Docs](https://dev.mysql.com/downloads/connector/j/)
##### Dependencies
<table class="table-configuration">
<tr>
@ -245,6 +291,96 @@ Here are some examples you can refer to. Including the below connectors, you can
</tr>
</table>
[Maven Repository: mysql:mysql-connector-java](https://mvnrepository.com/artifact/mysql/mysql-connector-java)
### MariaDB
<img src="../assets/themes/zeppelin/img/docs-img/mariadb_setting.png" width="600px" />
##### Properties
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>default.driver</td>
<td>org.mariadb.jdbc.Driver</td>
</tr>
<tr>
<td>default.url</td>
<td>jdbc:mariadb://localhost:3306</td>
</tr>
<tr>
<td>default.user</td>
<td>mariadb_user</td>
</tr>
<tr>
<td>default.password</td>
<td>mariadb_password</td>
</tr>
</table>
[MariaDB JDBC Driver Docs](https://mariadb.com/kb/en/mariadb/about-mariadb-connector-j/)
##### Dependencies
<table class="table-configuration">
<tr>
<th>Artifact</th>
<th>Excludes</th>
</tr>
<tr>
<td>org.mariadb.jdbc:mariadb-java-client:1.5.4</td>
<td></td>
</tr>
</table>
[Maven Repository: org.mariadb.jdbc:mariadb-java-client](https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client)
### Redshift
<img src="../assets/themes/zeppelin/img/docs-img/redshift_setting.png" width="600px" />
##### Properties
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Value</th>
</tr>
<tr>
<td>default.driver</td>
<td>com.amazon.redshift.jdbc42.Driver</td>
</tr>
<tr>
<td>default.url</td>
<td>jdbc:redshift://your-redshift-instance-address.redshift.amazonaws.com:5439/your-database</td>
</tr>
<tr>
<td>default.user</td>
<td>redshift_user</td>
</tr>
<tr>
<td>default.password</td>
<td>redshift_password</td>
</tr>
</table>
[AWS Redshift JDBC Driver Docs](http://docs.aws.amazon.com/redshift/latest/mgmt/configure-jdbc-connection.html)
##### Dependencies
<table class="table-configuration">
<tr>
<th>Artifact</th>
<th>Excludes</th>
</tr>
<tr>
<td>com.amazonaws:aws-java-sdk-redshift:1.11.51</td>
<td></td>
</tr>
</table>
[Maven Repository: com.amazonaws:aws-java-sdk-redshift](https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-redshift)
### Apache Hive
<img src="../assets/themes/zeppelin/img/docs-img/hive_setting.png" width="600px" />
@ -273,6 +409,9 @@ Here are some examples you can refer to. Including the below connectors, you can
</tr>
</table>
[Apache Hive 1 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
[Apache Hive 2 JDBC Driver Docs](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-JDBC)
##### Dependencies
<table class="table-configuration">
<tr>
@ -289,6 +428,8 @@ Here are some examples you can refer to. Including the below connectors, you can
</tr>
</table>
[Maven Repository : org.apache.hive:hive-jdbc](https://mvnrepository.com/artifact/org.apache.hive/hive-jdbc)
### Apache Phoenix
Phoenix supports `thick` and `thin` connection types:
@ -338,6 +479,8 @@ Use the appropriate `default.driver`, `default.url`, and the dependency artifact
</tr>
</table>
[Maven Repository: org.apache.phoenix:phoenix-core](https://mvnrepository.com/artifact/org.apache.phoenix/phoenix-core)
#### Thin client connection
<img src="../assets/themes/zeppelin/img/docs-img/phoenix_thin_setting.png" width="600px" />
@ -388,6 +531,8 @@ Before Adding one of the below dependencies, check the Phoenix version first.
</tr>
</table>
[Maven Repository: org.apache.phoenix:phoenix-queryserver-client](https://mvnrepository.com/artifact/org.apache.phoenix/phoenix-queryserver-client)
### Apache Tajo
<img src="../assets/themes/zeppelin/img/docs-img/tajo_setting.png" width="600px" />
@ -408,6 +553,8 @@ Before Adding one of the below dependencies, check the Phoenix version first.
</tr>
</table>
[Apache Tajo JDBC Driver Docs](https://tajo.apache.org/docs/current/jdbc_driver.html)
##### Dependencies
<table class="table-configuration">
<tr>
@ -420,5 +567,7 @@ Before Adding one of the below dependencies, check the Phoenix version first.
</tr>
</table>
[Maven Repository: org.apache.tajo:tajo-jdbc](https://mvnrepository.com/artifact/org.apache.tajo/tajo-jdbc)
## Bug reporting
If you find a bug using JDBC interpreter, please create a [JIRA](https://issues.apache.org/jira/browse/ZEPPELIN) ticket.

86
docs/interpreter/kylin.md Normal file
View file

@ -0,0 +1,86 @@
---
layout: page
title: "Apache Kylin Interpreter for Apache Zeppelin"
description: "Apache Kylin™ is an open source Distributed Analytics Engine designed to provide SQL interface and multi-dimensional analysis (OLAP) on Hadoop supporting extremely large datasets, original contributed from eBay Inc.
."
group: interpreter
---
<!--
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.
-->
{% include JB/setup %}
# Apache Kylin Interpreter for Apache Zeppelin
<div id="toc"></div>
## Overview
[Apache Kylin](https://kylin.apache.org/) is an open source Distributed Analytics Engine designed to provide SQL interface and multi-dimensional analysis (OLAP) on Hadoop supporting extremely large datasets, original contributed from eBay Inc. The interpreter assumes that Apache Kylin has been installed and you can connect to Apache Kylin from the machine Apache Zeppelin is installed.
To get start with Apache Kylin, please see [Apache Kylin Quickstart](https://kylin.apache.org/docs15/index.html).
## Configuration
<table class="table-configuration">
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Default</th>
<th>Description</th>
</tr>
<tr>
<td>kylin.api.url </td>
<td>http://localhost:7070/kylin/api/query</td>
<td>kylin query POST API <br/> The format can be like http://&lt;host&gt;:&lt;port&gt;/kylin/api/query</td>
</tr>
<tr>
<td>kylin.api.user</td>
<td>ADMIN</td>
<td>kylin user</td>
</tr>
<tr>
<td>kylin.api.password</td>
<td>KYLIN</td>
<td>kylin password</td>
</tr>
<tr>
<td>kylin.query.project</td>
<td>learn_kylin</td>
<td>String, Project to perform query.</td>
</tr>
<tr>
<td>kylin.query.ispartial</td>
<td>true</td>
<td>true|false <br/> (@Deprecated since Apache Kylin V1.5) <br/> Whether accept a partial result or not, default be “false”. Set to “false” for production use.</td>
</tr>
<tr>
<td>kylin.query.limit</td>
<td>5000</td>
<td>int, Query limit <br/> If limit is set in sql, perPage will be ignored.</td>
</tr>
<tr>
<td>kylin.query.offset</td>
<td>0</td>
<td>int, Query offset <br/> If offset is set in sql, curIndex will be ignored.</td>
</tr>
</table>
</table>
## Using the Apache Kylin Interpreter
In a paragraph, use `%kylin` to select the **kylin** interpreter and then input sql.
```
%kylin
select count(*) from kylin_sales group by part_dt
```

View file

@ -78,13 +78,6 @@ print (z.select("f1",[("o1","1"),("o2","2")],"2"))
print("".join(z.checkbox("f3", [("o1","1"), ("o2","2")],["1"])))
```
## Zeppelin features not fully supported by the Python Interpreter
* Interrupt a paragraph execution (`cancel()` method) is currently only supported in Linux and MacOs. If interpreter runs in another operating system (for instance MS Windows) , interrupt a paragraph will close the whole interpreter. A JIRA ticket ([ZEPPELIN-893](https://issues.apache.org/jira/browse/ZEPPELIN-893)) is opened to implement this feature in a next release of the interpreter.
* Progression bar in webUI (`getProgress()` method) is currently not implemented.
* Code-completion is currently not implemented.
## Matplotlib integration
The python interpreter can display matplotlib figures inline automatically using the `pyplot` module:
@ -166,3 +159,11 @@ Otherwise it can be referred to as `%python.sql`
## Technical description
For in-depth technical details on current implementation please refer to [python/README.md](https://github.com/apache/zeppelin/blob/master/python/README.md).
### Some features not yet implemented in the Python Interpreter
* Interrupt a paragraph execution (`cancel()` method) is currently only supported in Linux and MacOs. If interpreter runs in another operating system (for instance MS Windows) , interrupt a paragraph will close the whole interpreter. A JIRA ticket ([ZEPPELIN-893](https://issues.apache.org/jira/browse/ZEPPELIN-893)) is opened to implement this feature in a next release of the interpreter.
* Progression bar in webUI (`getProgress()` method) is currently not implemented.
* Code-completion is currently not implemented.

168
docs/interpreter/scio.md Normal file
View file

@ -0,0 +1,168 @@
---
layout: page
title: "Scio Interpreter for Apache Zeppelin"
description: "Scio is a Scala DSL for Apache Beam/Google Dataflow model."
group: interpreter
---
<!--
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.
-->
{% include JB/setup %}
# Scio Interpreter for Apache Zeppelin
<div id="toc"></div>
## Overview
Scio is a Scala DSL for [Google Cloud Dataflow](https://github.com/GoogleCloudPlatform/DataflowJavaSDK) and [Apache Beam](http://beam.incubator.apache.org/) inspired by [Spark](http://spark.apache.org/) and [Scalding](https://github.com/twitter/scalding). See the current [wiki](https://github.com/spotify/scio/wiki) and [API documentation](http://spotify.github.io/scio/) for more information.
## Configuration
<table class="table-configuration">
<tr>
<th>Name</th>
<th>Default Value</th>
<th>Description</th>
</tr>
<tr>
<td>zeppelin.scio.argz</td>
<td>--runner=InProcessPipelineRunner</td>
<td>Scio interpreter wide arguments. Documentation: https://github.com/spotify/scio/wiki#options and https://cloud.google.com/dataflow/pipelines/specifying-exec-params</td>
</tr>
<tr>
<td>zeppelin.scio.maxResult</td>
<td>1000</td>
<td>Max number of SCollection results to display</td>
</tr>
</table>
## Enabling the Scio Interpreter
In a notebook, to enable the **Scio** interpreter, click the **Gear** icon and select **beam** (**beam.scio**).
## Using the Scio Interpreter
In a paragraph, use `$beam.scio` to select the **Scio** interpreter. You can use it much the same way as vanilla Scala REPL and [Scio REPL](https://github.com/spotify/scio/wiki/Scio-REPL). State (like variables, imports, execution etc) is shared among all *Scio* paragraphs. There is a special variable **argz** which holds arguments from Scio interpreter settings. The easiest way to proceed is to create a Scio context via standard `ContextAndArgs`.
```scala
$beam.scio
val (sc, args) = ContextAndArgs(argz)
```
Use `sc` context the way you would in regular pipeline/REPL.
Example:
```scala
$beam.scio
val (sc, args) = ContextAndArgs(argz)
sc.parallelize(Seq("foo", "foo", "bar")).countByValue.closeAndDisplay()
```
If you close Scio context, go ahead an create a new one using `ContextAndArgs`. Please refer to [Scio wiki](https://github.com/spotify/scio/wiki) for more complex examples. You can close Scio context much the same way as in Scio REPL, and use Zeppelin display helpers to synchronously close and display results - read more below.
### Progress
There can be only one paragraph running at a time. There is no notion of overall progress, thus progress bar will be `0`.
### SCollection display helpers
Scio interpreter comes with display helpers to ease working with Zeppelin notebooks. Simply use `closeAndDisplay()` on `SCollection` to close context and display the results. The number of results is limited by `zeppelin.scio.maxResult` (by default 1000).
Supported `SCollection` types:
* Scio's typed BigQuery
* Scala's Products (case classes, tuples)
* Google BigQuery's TableRow
* Apache Avro
* All Scala's `AnyVal`
#### Helper methods
There are different helper methods for different objects. You can easily display results from `SCollection`, `Future[Tap]` and `Tap`.
##### `SCollection` helper
`SCollection` has `closeAndDisplay` Zeppelin helper method for types listed above. Use it to synchronously close Scio context, once available pull and display results.
##### `Future[Tap]` helper
`Future[Tap]` has `waitAndDisplay` Zeppelin helper method for types listed above. Use it synchronously wait for results, once available pull and display results.
##### `Tap` helper
`Tap` has `display` Zeppelin helper method for types listed above. Use it to pull and display results.
### Examples
#### BigQuery example:
```scala
$beam.scio
@BigQueryType.fromQuery("""|SELECT departure_airport,count(case when departure_delay>0 then 1 else 0 end) as no_of_delays
|FROM [bigquery-samples:airline_ontime_data.flights]
|group by departure_airport
|order by 2 desc
|limit 10""".stripMargin) class Flights
val (sc, args) = ContextAndArgs(argz)
sc.bigQuerySelect(Flights.query).closeAndDisplay(Flights.schema)
```
#### BigQuery typed example:
```scala
$beam.scio
@BigQueryType.fromQuery("""|SELECT departure_airport,count(case when departure_delay>0 then 1 else 0 end) as no_of_delays
|FROM [bigquery-samples:airline_ontime_data.flights]
|group by departure_airport
|order by 2 desc
|limit 10""".stripMargin) class Flights
val (sc, args) = ContextAndArgs(argz)
sc.typedBigQuery[Flights]().flatMap(_.no_of_delays).mean.closeAndDisplay()
```
#### Avro example:
```scala
$beam.scio
import com.spotify.data.ExampleAvro
val (sc, args) = ContextAndArgs(argz)
sc.avroFile[ExampleAvro]("gs://<bucket>/tmp/my.avro").take(10).closeAndDisplay()
```
#### Avro example with a view schema:
```scala
$beam.scio
import com.spotify.data.ExampleAvro
import org.apache.avro.Schema
val (sc, args) = ContextAndArgs(argz)
val view = Schema.parse("""{"type":"record","name":"ExampleAvro","namespace":"com.spotify.data","fields":[{"name":"track","type":"string"}, {"name":"artist", "type":"string"}]}""")
sc.avroFile[EndSongCleaned]("gs://<bucket>/tmp/my.avro").take(10).closeAndDisplay(view)
```
### Google credentials
Scio Interpreter will try to infer your Google Cloud credentials from its environment, it will take into the account:
* `argz` interpreter settings ([doc](https://github.com/spotify/scio/wiki#options))
* environment variable (`GOOGLE_APPLICATION_CREDENTIALS`)
* gcloud configuration
#### BigQuery macro credentials
Currently BigQuery project for macro expansion is inferred using Google Dataflow's [DefaultProjectFactory().create()](https://github.com/GoogleCloudPlatform/DataflowJavaSDK/blob/master/sdk/src/main/java/com/google/cloud/dataflow/sdk/options/GcpOptions.java#L187)

View file

@ -23,8 +23,7 @@ limitations under the License.
<div id="toc"></div>
There are multiple ways to enable authentication in Apache Zeppelin. This page describes HTTP basic auth using NGINX.
One option is to use [Basic Access Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication).
[Build in authentication mechanism](./shiroauthentication.html) is recommended way for authentication. In case of you want authenticate using NGINX and [HTTP basic auth](https://en.wikipedia.org/wiki/Basic_access_authentication), please read this document.
## HTTP Basic Authentication using NGINX

View file

@ -33,22 +33,10 @@ You can setup **Zeppelin notebook authentication** in some simple steps.
### 1. Enable Shiro
By default in `conf`, you will find `shiro.ini.template`, this file is used as an example and it is strongly recommended
to create a `shiro.ini` file by doing the following command line `cp conf/shiro.ini.template conf/shiro.ini`.
to create a `shiro.ini` file by doing the following command line
### 2. Secure the HTTP channel
To secure the HTTP channel, you have to change both **anon** and **authc** settings in `conf/shiro.ini`. In here, **anon** means "the access is anonymous" and **authc** means "formed auth security".
The default status of them is
```
/** = anon
#/** = authc
```
Deactivate the line "/** = anon" and activate the line "/** = authc" in `conf/shiro.ini` file.
```
#/** = anon
/** = authc
```bash
cp conf/shiro.ini.template conf/shiro.ini
```
For the further information about `shiro.ini` file format, please refer to [Shiro Configuration](http://shiro.apache.org/configuration.html#Configuration-INISections).
@ -193,3 +181,9 @@ If you want to grant this permission to other users, you can change **roles[ ]**
<br/>
> **NOTE :** All of the above configurations are defined in the `conf/shiro.ini` file. This documentation is originally from [SECURITY-README.md](https://github.com/apache/zeppelin/blob/master/SECURITY-README.md).
## Other authentication methods
- [HTTP Basic Authentication using NGINX](./authentication.html)

View file

@ -313,13 +313,6 @@
<includeScope>runtime</includeScope>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-artifact</id>
<phase>package</phase>

10
pom.xml
View file

@ -75,6 +75,7 @@
<module>elasticsearch</module>
<module>bigquery</module>
<module>alluxio</module>
<module>scio</module>
<module>zeppelin-web</module>
<module>zeppelin-server</module>
<module>zeppelin-distribution</module>
@ -589,7 +590,14 @@
<module>beam</module>
</modules>
</profile>
<profile>
<id>scio</id>
<modules>
<module>scio</module>
</modules>
</profile>
<profile>
<id>examples</id>
<modules>

View file

@ -119,6 +119,7 @@ class PyZeppelinContext(object):
def __init__(self):
self.max_result = 1000
self._displayhook = lambda *args: None
self._setup_matplotlib()
def input(self, name, defaultValue=""):
print(self.errorMsg)
@ -206,7 +207,7 @@ class PyZeppelinContext(object):
try:
import matplotlib
except ImportError:
pass
return
# Make sure custom backends are available in the PYTHONPATH
rootdir = os.environ.get('ZEPPELIN_HOME', os.getcwd())
mpl_path = os.path.join(rootdir, 'interpreter', 'lib', 'python')
@ -217,7 +218,7 @@ class PyZeppelinContext(object):
try:
matplotlib.use('module://backend_zinline')
import backend_zinline
# Everything looks good so make config assuming that we are using
# an inline backend
self._displayhook = backend_zinline.displayhook
@ -231,4 +232,3 @@ class PyZeppelinContext(object):
z = PyZeppelinContext()
z._setup_matplotlib()

View file

@ -26,6 +26,7 @@ class Py4jZeppelinContext(PyZeppelinContext):
"""A context impl that uses Py4j to communicate to JVM
"""
def __init__(self, z):
PyZeppelinContext.__init__(self)
self.z = z
self.paramOption = gateway.jvm.org.apache.zeppelin.display.Input.ParamOption
self.javaList = gateway.jvm.java.util.ArrayList

18
scio/README.md Normal file
View file

@ -0,0 +1,18 @@
Scio interpreter for Apache Zeppelin
====================================
## Raison d'être:
Provide Scio Interpreter for Zeppelin.
## Build
```
mvn -pl zeppelin-interpreter,zeppelin-display,scio -DskipTests package
```
## Test
```
mvn -pl scio,zeppelin-display,zeppelin-interpreter -Dtest='org.apache.zeppelin.scio.*' -DfailIfNoTests=false test
```

240
scio/pom.xml Normal file
View file

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one or more
~ contributor license agreements. See the NOTICE file distributed with
~ this work for additional information regarding copyright ownership.
~ The ASF licenses this file to You under the Apache License, Version 2.0
~ (the "License"); you may not use this file except in compliance with
~ the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>zeppelin</artifactId>
<groupId>org.apache.zeppelin</groupId>
<version>0.7.0-SNAPSHOT</version>
<relativePath>..</relativePath>
</parent>
<groupId>org.apache.zeppelin</groupId>
<artifactId>zeppelin-scio_2.10</artifactId>
<packaging>jar</packaging>
<version>0.7.0-SNAPSHOT</version>
<name>Zeppelin: Scio</name>
<description>Zeppelin Scio support</description>
<properties>
<scio.version>0.2.4</scio.version>
</properties>
<dependencies>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>zeppelin-interpreter</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.spotify</groupId>
<artifactId>scio-repl_${scala.binary.version}</artifactId>
<version>${scio.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>14.0.1</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-compiler</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
<version>${scala.version}</version>
</dependency>
<!--TEST-->
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_${scala.binary.version}</artifactId>
<version>${scalatest.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.3.1</version>
<executions>
<execution>
<id>enforce</id>
<phase>none</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>reference.conf</resource>
</transformer>
</transformers>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/../../interpreter/scio</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>false</overWriteSnapshots>
<overWriteIfNewer>true</overWriteIfNewer>
<includeScope>runtime</includeScope>
<artifactItems>
<artifactItem>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
<type>${project.packaging}</type>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<!-- Plugin to compile Scala code -->
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<phase>compile</phase>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
<phase>test-compile</phase>
</execution>
<execution>
<phase>process-resources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Plugin to compile avro for tests -->
<plugin>
<groupId>org.apache.avro</groupId>
<artifactId>avro-maven-plugin</artifactId>
<version>1.7.7</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>schema</goal>
</goals>
<configuration>
<sourceDirectory>${project.basedir}/src/test/avro/</sourceDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,41 @@
/*
* 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.scio
import com.google.cloud.dataflow.sdk.options.PipelineOptions
import com.spotify.scio.repl.ReplScioContext
import com.spotify.scio.{Args, ScioContext}
/**
* Convenience object for creating [[com.spotify.scio.ScioContext]] and [[com.spotify.scio.Args]].
*/
object ContextAndArgs {
def apply(argz: Array[String]): (ScioContext, Args) = {
val (dfOpts, args) = ScioContext.parseArguments[PipelineOptions](argz)
val nextReplJar = this
.getClass
.getClassLoader
.asInstanceOf[{def getNextReplCodeJarPath: String}].getNextReplCodeJarPath
val sc = new ReplScioContext(dfOpts, List(nextReplJar))
sc.setName("sciozeppelin")
(sc, args)
}
}

View file

@ -0,0 +1,160 @@
/*
* 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.scio
import com.google.api.services.bigquery.model.TableSchema
import com.spotify.scio.bigquery._
import org.apache.avro.Schema
import org.apache.avro.generic.GenericRecord
import scala.reflect.ClassTag
/**
* Set of helpers for Zeppelin Display system.
*/
private[scio] object DisplayHelpers {
private[scio] val sCollectionEmptyMsg =
"\n%html <font color=red>Result SCollection is empty!</font>\n"
private val maxResults = Integer.getInteger("zeppelin.scio.maxResult", 1000)
private[scio] val tab = "\t"
private[scio] val newline = "\n"
private[scio] val table = "%table"
private[scio] val rowLimitReachedMsg =
s"$newline<font color=red>Results are limited to " + maxResults + s" rows.</font>$newline"
private[scio] val bQSchemaIncomplete =
s"$newline<font color=red>Provided BigQuery Schema has not fields!</font>$newline"
private def notifyIfTruncated(it: Iterator[_]): Unit = {
if(it.hasNext) println(rowLimitReachedMsg)
}
/**
* Displays [[AnyVal]] values from given [[Iterator]].
*/
private[scio] def displayAnyVal[T: ClassTag](it: Iterator[T], printer: (T) => String): Unit = {
if (it.isEmpty) {
println(sCollectionEmptyMsg)
} else {
println(s"$table value$newline${it.take(maxResults).map(printer).mkString(newline)}")
notifyIfTruncated(it)
}
}
/**
* Displays [[String]] values from given [[Iterator]].
*/
private[scio] def displayString[T: ClassTag](it: Iterator[T], printer: (T) => String): Unit = {
if (it.isEmpty) {
println(sCollectionEmptyMsg)
} else {
println(s"$table value$newline${it.take(maxResults).map(printer).mkString(newline)}")
notifyIfTruncated(it)
}
}
/**
* Displays [[com.google.cloud.dataflow.sdk.values.KV]] values from given [[Iterator]].
*/
private[scio] def displayKV[K: ClassTag, V: ClassTag](it: Iterator[(K,V)]): Unit = {
if (it.isEmpty) {
println(sCollectionEmptyMsg)
} else {
val content = it.take(maxResults).map{ case (k, v) => s"$k$tab$v" }.mkString(newline)
println(s"$table key${tab}value$newline$content")
notifyIfTruncated(it)
}
}
/**
* Displays [[Product]] values from given [[Iterator]].
*/
private[scio] def displayProduct[T: ClassTag](it: Iterator[T])
(implicit ev: T <:< Product): Unit = {
if (it.isEmpty) {
println(sCollectionEmptyMsg)
} else {
val first = it.next()
//TODO is this safe field name to value iterator?
val fieldNames = first.getClass.getDeclaredFields.map(_.getName)
val header = fieldNames.mkString(tab)
val firstStr = first.productIterator.mkString(tab)
val content = it.take(maxResults - 1).map(_.productIterator.mkString(tab)).mkString(newline)
println(s"$table $header$newline$firstStr$newline$content")
notifyIfTruncated(it)
}
}
/**
* Displays Avro values from given [[Iterator]] using optional [[Schema]].
* @param schema optional "view" schema, otherwise schema is inferred from the first object
*/
private[scio] def displayAvro[T: ClassTag](it: Iterator[T], schema: Schema = null)
(implicit ev: T <:< GenericRecord): Unit = {
if (it.isEmpty) {
println(sCollectionEmptyMsg)
} else {
val first = it.next()
import collection.JavaConverters._
val fieldNames = if (schema != null) {
schema.getFields.iterator().asScala.map(_.name()).toArray
} else {
first.getSchema.getFields.iterator.asScala.map(_.name()).toArray
}
val header = fieldNames.mkString(tab)
val firstStr = fieldNames.map(first.get).mkString(tab)
val content = it.take(maxResults - 1)
.map(r => fieldNames.map(r.get).mkString(tab))
.mkString(newline)
println(s"$table $header$newline$firstStr$newline$content")
notifyIfTruncated(it)
}
}
/**
* Displays [[TableRow]] values from given [[Iterator]] using specified [[TableSchema]].
*/
private[scio] def displayBQTableRow[T: ClassTag](it: Iterator[T], schema: TableSchema)
(implicit ev: T <:< TableRow) : Unit = {
if (it.isEmpty) {
println(sCollectionEmptyMsg)
} else {
import collection.JavaConverters._
val fieldsOp = Option(schema.getFields)
fieldsOp match {
case None => println(bQSchemaIncomplete)
case Some(f) => {
val fields = f.asScala.map(_.getName).toArray
val header = fields.mkString(tab)
val content = it.take(maxResults)
.map(r => fields.map(r.get).mkString(tab))
.mkString(newline)
println(s"$table $header$newline$content")
notifyIfTruncated(it)
}
}
}
}
}

View file

@ -0,0 +1,105 @@
/*
* 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.scio
import com.google.api.services.bigquery.model.TableSchema
import com.spotify.scio._
import com.spotify.scio.bigquery._
import com.spotify.scio.values.SCollection
import org.apache.avro.Schema
import org.apache.avro.generic.GenericRecord
import scala.reflect.ClassTag
/**
* Implicit Zeppelin display helpers for SCollection.
*/
object DisplaySCollectionImplicits {
private def materialize[T: ClassTag](self: SCollection[T]) = {
val f = self.materialize
self.context.close()
f
}
// TODO: scala 2.11
// implicit class ZeppelinSCollection[T: ClassTag](private val self: SCollection[T])(implicit ev: T <:< AnyVal) extends AnyVal {
implicit class ZeppelinSCollection[T: ClassTag](val self: SCollection[T])
(implicit ev: T <:< AnyVal) {
/** Convenience method to close the current [[com.spotify.scio.ScioContext]]
* and display elements from SCollection. */
def closeAndDisplay(printer: (T) => String = (e: T) => e.toString): Unit = {
DisplayTapImplicits.ZeppelinTap(materialize(self).waitForResult()).display(printer)
}
}
// TODO: scala 2.11
// implicit class ZeppelinSCollection[T: ClassTag](private val self: SCollection[T]) extends AnyVal {
implicit class ZeppelinStringSCollection[T: ClassTag](val self: SCollection[T])
(implicit ev: T <:< String) {
/** Convenience method to close the current [[com.spotify.scio.ScioContext]]
* and display elements from SCollection. */
def closeAndDisplay(printer: (T) => String = (e: T) => e.toString): Unit = {
DisplayTapImplicits.ZeppelinStringTap(materialize(self).waitForResult()).display(printer)
}
}
// TODO: scala 2.11
// implicit class ZeppelinKVSCollection[K: ClassTag, V: ClassTag](val self: SCollection[(K, V)]) extends AnyVal {
implicit class ZeppelinKVSCollection[K: ClassTag, V: ClassTag](val self: SCollection[(K, V)]) {
/** Convenience method to close the current [[com.spotify.scio.ScioContext]]
* and display elements from KV SCollection. */
def closeAndDisplay(): Unit = {
DisplayTapImplicits.ZeppelinKVTap(materialize(self).waitForResult()).display()
}
}
// TODO: scala 2.11
// implicit class ZeppelinProductSCollection[T: ClassTag](val self: SCollection[T])(implicit ev: T <:< Product) extends AnyVal {
implicit class ZeppelinProductSCollection[T: ClassTag](val self: SCollection[T])
(implicit ev: T <:< Product) {
/** Convenience method to close the current [[com.spotify.scio.ScioContext]]
* and display elements from Product like SCollection */
def closeAndDisplay(): Unit = {
DisplayTapImplicits.ZeppelinProductTap(materialize(self).waitForResult()).display()
}
}
// TODO: scala 2.11
// implicit class ZeppelinAvroSCollection[T: ClassTag](val self: SCollection[T])(implicit ev: T <:< GenericRecord) extends AnyVal {
implicit class ZeppelinAvroSCollection[T: ClassTag](val self: SCollection[T])
(implicit ev: T <:< GenericRecord) {
/** Convenience method to close the current [[com.spotify.scio.ScioContext]]
* and display elements from Avro like SCollection */
def closeAndDisplay(schema: Schema = null): Unit = {
DisplayTapImplicits.ZeppelinAvroTap(materialize(self).waitForResult()).display(schema)
}
}
// TODO: scala 2.11
// implicit class ZeppelinBQTableSCollection[T: ClassTag](val self: SCollection[T])(implicit ev: T <:< TableRow) extends AnyVal {
implicit class ZeppelinBQTableSCollection[T: ClassTag](val self: SCollection[T])
(implicit ev: T <:< TableRow) {
/** Convenience method to close the current [[com.spotify.scio.ScioContext]]
* and display elements from TableRow like SCollection */
def closeAndDisplay(schema: TableSchema): Unit = {
DisplayTapImplicits.ZeppelinBQTableTap(materialize(self).waitForResult()).display(schema)
}
}
}

View file

@ -0,0 +1,154 @@
/*
* 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.scio
import com.google.api.services.bigquery.model.TableSchema
import com.spotify.scio.bigquery.TableRow
import com.spotify.scio.io.Tap
import com.spotify.scio._
import org.apache.avro.Schema
import org.apache.avro.generic.GenericRecord
import scala.concurrent.Future
import scala.reflect.ClassTag
/**
* Implicit Zeppelin display helpers for [[Tap]] and [[Future]] of a [[Tap]].
*/
object DisplayTapImplicits {
// TODO: scala 2.11
// implicit class ZeppelinTap[T: ClassTag](private val self: Tap[T])(implicit ev: T <:< AnyVal) extends AnyVal {
implicit class ZeppelinTap[T: ClassTag](val self: Tap[T])
(implicit ev: T <:< AnyVal) {
/** Convenience method to display [[com.spotify.scio.io.Tap]] of AnyVal. */
def display(printer: (T) => String = (e: T) => e.toString): Unit = {
DisplayHelpers.displayAnyVal(self.value, printer)
}
}
// TODO: scala 2.11
// implicit class ZeppelinFutureTap[T: ClassTag](private val self: Future[Tap[T]])(implicit ev: T <:< AnyVal) extends AnyVal {
implicit class ZeppelinFutureTap[T: ClassTag](val self: Future[Tap[T]])
(implicit ev: T <:< AnyVal) {
/** Convenience method to display [[Future]] of a [[com.spotify.scio.io.Tap]] of AnyVal. */
def waitAndDisplay(printer: (T) => String = (e: T) => e.toString): Unit = {
ZeppelinTap(self.waitForResult()).display(printer)
}
}
// TODO: scala 2.11
// implicit class ZeppelinStringTap[T: ClassTag](private val self: Tap[T])(implicit ev: T <:< String) extends AnyVal {
implicit class ZeppelinStringTap[T: ClassTag](val self: Tap[T])
(implicit ev: T <:< String) {
/** Convenience method to display [[com.spotify.scio.io.Tap]] of Strings. */
def display(printer: (T) => String = (e: T) => e.toString): Unit = {
DisplayHelpers.displayString(self.value, printer)
}
}
// TODO: scala 2.11
// implicit class ZeppelinFutureStringTap[T: ClassTag](private val self: Tap[T])(implicit ev: T <:< String) extends AnyVal {
implicit class ZeppelinFutureStringTap[T: ClassTag](val self: Future[Tap[T]])
(implicit ev: T <:< String) {
/** Convenience method to display [[Future]] of a [[com.spotify.scio.io.Tap]] of Strings. */
def waitAndDisplay(printer: (T) => String = (e: T) => e.toString): Unit = {
ZeppelinStringTap(self.waitForResult()).display(printer)
}
}
// TODO: scala 2.11
// implicit class ZeppelinKVTap[K: ClassTag, V: ClassTag](val self: Tap[(K, V)]) extends AnyVal {
implicit class ZeppelinKVTap[K: ClassTag, V: ClassTag](val self: Tap[(K, V)]) {
/** Convenience method to display [[com.spotify.scio.io.Tap]] of KV. */
def display(): Unit = {
DisplayHelpers.displayKV(self.value)
}
}
// TODO: scala 2.11
// implicit class ZeppelinFutureKVTap[K: ClassTag, V: ClassTag](val self: Future[Tap[(K, V)]]) extends AnyVal {
implicit class ZeppelinFutureKVTap[K: ClassTag, V: ClassTag](val self: Future[Tap[(K, V)]]) {
/** Convenience method to display [[Future]] of a [[com.spotify.scio.io.Tap]] of KV. */
def waitAndDisplay(): Unit = {
ZeppelinKVTap(self.waitForResult()).display()
}
}
// TODO: scala 2.11
// implicit class ZeppelinProductTap[T: ClassTag](val self: Tap[T])(implicit ev: T <:< Product) extends AnyVal {
implicit class ZeppelinProductTap[T: ClassTag](val self: Tap[T])
(implicit ev: T <:< Product) {
/** Convenience method to display [[com.spotify.scio.io.Tap]] of Product. */
def display(): Unit = {
DisplayHelpers.displayProduct(self.value)
}
}
// TODO: scala 2.11
// implicit class ZeppelinFutureProductTap[T: ClassTag](val self: Future[Tap[T]])(implicit ev: T <:< Product) extends AnyVal {
implicit class ZeppelinFutureProductTap[T: ClassTag](val self: Future[Tap[T]])
(implicit ev: T <:< Product) {
/** Convenience method to display [[Future]] of a [[com.spotify.scio.io.Tap]] of Product. */
def waitAndDisplay(): Unit = {
ZeppelinProductTap(self.waitForResult()).display()
}
}
// TODO: scala 2.11
// implicit class ZeppelinAvroTap[T: ClassTag](val self: Tap[T])(implicit ev: T <:< GenericRecord) extends AnyVal {
implicit class ZeppelinAvroTap[T: ClassTag](val self: Tap[T])
(implicit ev: T <:< GenericRecord) {
/** Convenience method to display [[com.spotify.scio.io.Tap]] of Avro. */
def display(schema: Schema = null): Unit = {
DisplayHelpers.displayAvro(self.value, schema)
}
}
// TODO: scala 2.11
// implicit class ZeppelinFutureAvroTap[T: ClassTag](val self: Future[Tap[T]])(implicit ev: T <:< GenericRecord) extends AnyVal {
implicit class ZeppelinFutureAvroTap[T: ClassTag](val self: Future[Tap[T]])
(implicit ev: T <:< GenericRecord) {
/** Convenience method to display [[Future]] of a [[com.spotify.scio.io.Tap]] of Avro. */
def waitAndDisplay(schema: Schema = null): Unit = {
ZeppelinAvroTap(self.waitForResult()).display(schema)
}
}
// TODO: scala 2.11
// implicit class ZeppelinBQTableTap[T: ClassTag](val self: Tap[T])(implicit ev: T <:< TableRow) extends AnyVal {
implicit class ZeppelinBQTableTap[T: ClassTag](val self: Tap[T])
(implicit ev: T <:< TableRow) {
/** Convenience method to display [[com.spotify.scio.io.Tap]] of BigQuery TableRow. */
def display(schema: TableSchema): Unit = {
DisplayHelpers.displayBQTableRow(self.value, schema)
}
}
// TODO: scala 2.11
// implicit class ZeppelinFutureBQTableTap[T: ClassTag](val self: Future[Tap[T]])(implicit ev: T <:< TableRow) extends AnyVal {
implicit class ZeppelinFutureBQTableTap[T: ClassTag](val self: Future[Tap[T]])
(implicit ev: T <:< TableRow) {
/** Convenience method to display [[Future]] of a [[com.spotify.scio.io.Tap]] of BigQuery
* TableRow. */
def waitAndDisplay(schema: TableSchema): Unit = {
ZeppelinBQTableTap(self.waitForResult()).display(schema)
}
}
}

View file

@ -0,0 +1,201 @@
/*
* 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.scio
import java.beans.Introspector
import java.io.PrintStream
import java.util.Properties
import com.google.cloud.dataflow.sdk.options.{PipelineOptions, PipelineOptionsFactory}
import com.google.cloud.dataflow.sdk.runners.inprocess.InProcessPipelineRunner
import com.spotify.scio.repl.{ScioILoop, ScioReplClassLoader}
import org.apache.zeppelin.interpreter.Interpreter.FormType
import org.apache.zeppelin.interpreter.util.InterpreterOutputStream
import org.apache.zeppelin.interpreter.{Interpreter, InterpreterContext, InterpreterResult}
import org.slf4j.LoggerFactory
import scala.reflect.io.File
import scala.tools.nsc.GenericRunnerCommand
import scala.tools.nsc.interpreter.JPrintWriter
import scala.tools.nsc.util.ClassPath
/**
* Scio interpreter for Zeppelin.
*
* <ul>
* <li>{@code zeppelin.scio.argz} - Scio interpreter wide arguments</li>
* <li>{@code zeppelin.scio.maxResult} - Max number of SCollection results to display.</li>
* </ul>
*
* <p>
* How to use: <br/>
* {@code
* $beam.scio
* val (sc, args) = ContextAndArgs(argz)
* sc.parallelize(Seq("foo", "foo", "bar")).countByValue.closeAndDisplay()
* }
* </p>
*
*/
class ScioInterpreter(property: Properties) extends Interpreter(property) {
private val logger = LoggerFactory.getLogger(classOf[ScioInterpreter])
private var REPL: ScioILoop = _
val innerOut = new InterpreterOutputStream(logger)
override def open(): Unit = {
val argz = Option(getProperty("zeppelin.scio.argz"))
.getOrElse(s"--runner=${classOf[InProcessPipelineRunner].getSimpleName}")
.split(" ")
.map(_.trim)
.filter(_.nonEmpty)
.toList
// Process command line arguments into a settings object, and use that to start the REPL.
// We ignore params we don't care about - hence error function is empty
val command = new GenericRunnerCommand(argz, _ => ())
val settings = command.settings
settings.classpath.append(System.getProperty("java.class.path"))
settings.usejavacp.value = true
def classLoaderURLs(cl: ClassLoader): Array[java.net.URL] = cl match {
case null => Array()
case u: java.net.URLClassLoader => u.getURLs ++ classLoaderURLs(cl.getParent)
case _ => classLoaderURLs(cl.getParent)
}
classLoaderURLs(Thread.currentThread().getContextClassLoader)
.foreach(u => settings.classpath.append(u.getPath))
// We have to make sure that scala macros are expandable. paradise plugin has to be added to
// -Xplugin paths. In case of assembly - paradise is included in assembly jar - thus we add
// itself to -Xplugin. If shell is started from sbt or classpath, paradise jar has to be in
// classpath, we find it and add it to -Xplugin.
val thisJar = this.getClass.getProtectionDomain.getCodeSource.getLocation.getPath
// In some cases this may be `target/classes`
if(thisJar.endsWith(".jar")) settings.plugin.appendToValue(thisJar)
ClassPath
.split(settings.classpath.value)
.find(File(_).name.startsWith("paradise_"))
.foreach(settings.plugin.appendToValue)
// Force the repl to be synchronous, so all cmds are executed in the same thread
settings.Yreplsync.value = true
val jars = ClassPath.split(settings.classpath.value)
.flatMap(ClassPath.specToURL)
.toArray
val scioClassLoader = new ScioReplClassLoader(
jars ++ classLoaderURLs(Thread.currentThread().getContextClassLoader),
null,
Thread.currentThread.getContextClassLoader)
val (dfArgs, _) = parseAndPartitionArgs(argz)
REPL = new ScioILoop(scioClassLoader, dfArgs, None, new JPrintWriter(innerOut))
scioClassLoader.setRepl(REPL)
// Set classloader chain - expose top level abstract class loader down
// the chain to allow for readObject and latestUserDefinedLoader
// See https://gist.github.com/harrah/404272
settings.embeddedDefaults(scioClassLoader)
// No need for bigquery dumps
sys.props("bigquery.plugin.disable.dump") = true.toString
REPL.settings_=(settings)
REPL.createInterpreter()
REPL.interpret(s"""val argz = Array("${argz.mkString("\", \"")}")""")
REPL.interpret("import org.apache.zeppelin.scio.DisplaySCollectionImplicits._")
REPL.interpret("import org.apache.zeppelin.scio.DisplayTapImplicits._")
REPL.interpret("import org.apache.zeppelin.scio.ContextAndArgs")
}
private def parseAndPartitionArgs(args: List[String]): (List[String], List[String]) = {
import scala.collection.JavaConverters._
// Extract --pattern of all registered derived types of PipelineOptions
val classes = PipelineOptionsFactory.getRegisteredOptions.asScala + classOf[PipelineOptions]
val optPatterns = classes.flatMap { cls =>
cls.getMethods.flatMap { m =>
val n = m.getName
if ((!n.startsWith("get") && !n.startsWith("is")) ||
m.getParameterTypes.nonEmpty || m.getReturnType == classOf[Unit]) None
else Some(Introspector.decapitalize(n.substring(if (n.startsWith("is")) 2 else 3)))
}.map(s => s"--$s($$|=)".r)
}
// Split cmdlineArgs into 2 parts, optArgs for PipelineOptions and appArgs for Args
args.partition(arg => optPatterns.exists(_.findFirstIn(arg).isDefined))
}
override def close(): Unit = {
logger.info("Closing Scio interpreter!")
REPL.closeInterpreter()
}
override def interpret(code: String, context: InterpreterContext): InterpreterResult = {
val paragraphId = context.getParagraphId
val consoleOut = new PrintStream(innerOut)
System.setOut(consoleOut)
innerOut.setInterpreterOutput(context.out)
try {
import tools.nsc.interpreter.Results._
REPL.interpret(code) match {
case Success => {
logger.debug(s"Successfully executed `$code` in $paragraphId")
new InterpreterResult(InterpreterResult.Code.SUCCESS)
}
case Error => {
logger.error(s"Error executing `$code` in $paragraphId")
new InterpreterResult(InterpreterResult.Code.ERROR, "Interpreter error")
}
case Incomplete => {
logger.warn(s"Code `$code` not complete in $paragraphId")
new InterpreterResult(InterpreterResult.Code.INCOMPLETE, "Incomplete expression")
}
}
} catch {
case e: Exception =>
logger.info("Interpreter exception", e)
new InterpreterResult(InterpreterResult.Code.ERROR, e.getMessage)
} finally {
innerOut.flush()
innerOut.setInterpreterOutput(null)
consoleOut.flush()
}
}
override def cancel(context: InterpreterContext): Unit = {
// not implemented
}
override def getFormType: FormType = FormType.NATIVE
override def getProgress(context: InterpreterContext): Int = {
// not implemented
0
}
}

View file

@ -0,0 +1,12 @@
{
"type": "record",
"name": "Account",
"namespace": "org.apache.zeppelin.scio.avro",
"doc": "Record for an account",
"fields": [
{"name": "id", "type": "int"},
{"name": "type", "type": "string"},
{"name": "name", "type": "string"},
{"name": "amount", "type": "double"}
]
}

View file

@ -0,0 +1,118 @@
/*
* 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.scio;
import org.apache.zeppelin.display.AngularObjectRegistry;
import org.apache.zeppelin.display.GUI;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.resource.LocalResourcePool;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.junit.Before;
import org.junit.Test;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Properties;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ScioInterpreterTest {
private static ScioInterpreter repl;
private static InterpreterGroup intpGroup;
private InterpreterContext context;
private final String newline = "\n";
private InterpreterContext getNewContext() {
return new InterpreterContext("note", "id", "title", "text",
new AuthenticationInfo(),
new HashMap<String, Object>(),
new GUI(),
new AngularObjectRegistry(intpGroup.getId(), null),
new LocalResourcePool("id"),
new LinkedList<InterpreterContextRunner>(),
new InterpreterOutput(new InterpreterOutputListener() {
@Override
public void onAppend(InterpreterOutput out, byte[] line) {}
@Override
public void onUpdate(InterpreterOutput out, byte[] output) {}
}));
}
@Before
public void setUp() throws Exception {
if (repl == null) {
intpGroup = new InterpreterGroup();
intpGroup.put("note", new LinkedList<Interpreter>());
repl = new ScioInterpreter(new Properties());
repl.setInterpreterGroup(intpGroup);
intpGroup.get("note").add(repl);
repl.open();
}
context = getNewContext();
}
@Test
public void testBasicSuccess() {
assertEquals(InterpreterResult.Code.SUCCESS,
repl.interpret("val a = 1" + newline + "val b = 2", context).code());
}
@Test
public void testBasicSyntaxError() {
InterpreterResult error = repl.interpret("val a:Int = 'ds'", context);
assertEquals(InterpreterResult.Code.ERROR, error.code());
assertEquals("Interpreter error", error.message());
}
@Test
public void testBasicIncomplete() {
InterpreterResult incomplete = repl.interpret("val a = \"\"\"", context);
assertEquals(InterpreterResult.Code.INCOMPLETE, incomplete.code());
assertEquals("Incomplete expression", incomplete.message());
}
@Test
public void testBasicPipeline() {
assertEquals(InterpreterResult.Code.SUCCESS,
repl.interpret("val (sc, _) = ContextAndArgs(argz)" + newline
+ "sc.parallelize(1 to 10).closeAndCollect().toList", context).code());
}
@Test
public void testBasicMultiStepPipeline() {
final StringBuilder code = new StringBuilder();
code.append("val (sc, _) = ContextAndArgs(argz)").append(newline)
.append("val numbers = sc.parallelize(1 to 10)").append(newline)
.append("val results = numbers.closeAndCollect().toList").append(newline)
.append("println(results)");
assertEquals(InterpreterResult.Code.SUCCESS,
repl.interpret(code.toString(), context).code());
}
@Test
public void testException() {
InterpreterResult exception = repl.interpret("val (sc, _) = ContextAndArgs(argz)" + newline
+ "throw new Exception(\"test\")", context);
assertEquals(InterpreterResult.Code.ERROR, exception.code());
assertTrue(exception.message().length() > 0);
}
}

View file

@ -0,0 +1,22 @@
#
# 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.
#
log4j.rootLogger = INFO, stdout
log4j.appender.stdout = org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%d] ({%t} %F[%M]:%L) - %m%n

View file

@ -0,0 +1,55 @@
/*
* 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.scio
import org.apache.zeppelin.scio.util.TestUtils
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.{FlatSpec, Matchers}
/**
* Scala 2.11 DisplayHelpersTest tests.
*
* Most tests have test scope implicit imports due to scala 2.10 bug
* https://issues.scala-lang.org/browse/SI-3346
*
* Note: we can't depend on the order of data coming from SCollection.
*/
@RunWith(classOf[JUnitRunner]
class DisplayHelpersTestScala211 extends FlatSpec with Matchers {
import TestUtils._
// -----------------------------------------------------------------------------------------------
// Product SCollection Tests
// -----------------------------------------------------------------------------------------------
it should "support SCollection of Case Class of 23" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
val tupleHeader = s"$table " + (1 to 22).map(i => s"a$i$tab").mkString + "a23"
val o = captureOut {
sideEffectWithData(
Seq.fill(3)(CC23(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(tupleHeader) ++
Seq.fill(3)((1 to 22).map(i => s"$i$tab").mkString + "23"))
o.head should be(tupleHeader)
}
}

View file

@ -0,0 +1,22 @@
/*
* 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.scio
case class CC23(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int,
a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int,
a18: Int, a19: Int, a20: Int, a21: Int, a22: Int, a23: Int)

View file

@ -0,0 +1,548 @@
/*
* 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.scio
import com.google.api.services.bigquery.model.{TableFieldSchema, TableSchema}
import com.spotify.scio.bigquery._
import org.apache.avro.Schema
import org.apache.avro.Schema.Parser
import org.apache.avro.generic.{GenericData, GenericRecord}
import org.apache.zeppelin.scio.avro.Account
import org.apache.zeppelin.scio.util.TestUtils
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.{FlatSpec, Matchers}
/**
* DisplayHelpersTest tests.
*
* Most tests have test scope implicit imports due to scala 2.10 bug
* https://issues.scala-lang.org/browse/SI-3346
*
* Note: we can't depend on the order of data coming from SCollection.
*/
@RunWith(classOf[JUnitRunner])
class DisplayHelpersTest extends FlatSpec with Matchers {
private val testRowLimit = 20
sys.props("zeppelin.scio.maxResult") = 20.toString
import TestUtils._
// -----------------------------------------------------------------------------------------------
// AnyVal SCollection Tests
// -----------------------------------------------------------------------------------------------
private val anyValHeader = s"$table value"
"DisplayHelpers" should "support Integer SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(1, 2, 3)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"1",
"2",
"3")
o.head should be(anyValHeader)
}
it should "support Long SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(1L, 2L, 3L)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"1",
"2",
"3")
o.head should be(anyValHeader)
}
it should "support Double SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(1.0D, 2.0D, 3.0D)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"1.0",
"2.0",
"3.0")
o.head should be(anyValHeader)
}
it should "support Float SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(1.0F, 2.0F, 3.0F)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"1.0",
"2.0",
"3.0")
o.head should be(anyValHeader)
}
it should "support Short SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(1.toShort, 2.toShort, 3.toShort)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"1",
"2",
"3")
o.head should be(anyValHeader)
}
it should "support Byte SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(1.toByte, 2.toByte, 3.toByte)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"1",
"2",
"3")
o.head should be(anyValHeader)
}
it should "support Boolean SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq(true, false, true)) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"true",
"false",
"true")
o.head should be(anyValHeader)
}
it should "support Char SCollection via AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq('a', 'b', 'c')) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(anyValHeader,
"a",
"b",
"c")
o.head should be(anyValHeader)
}
it should "support SCollection of AnyVal over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(1 to 21) { in =>
in.closeAndDisplay()
}
}
o.size should be > testRowLimit
o.head should be(anyValHeader)
o.last should be(rowLimitReached)
}
it should "support empty SCollection of AnyVal" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinSCollection
val o = captureOut {
sideEffectWithData(Seq.empty[AnyVal]) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
// -----------------------------------------------------------------------------------------------
// String SCollection Tests
// -----------------------------------------------------------------------------------------------
private val stringHeader = s"$table value"
it should "support String SCollection" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinStringSCollection
val o = captureOut {
sideEffectWithData(Seq("a","b","c")) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(stringHeader,
"a",
"b",
"c")
o.head should be (stringHeader)
}
it should "support empty SCollection of String" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinStringSCollection
val o = captureOut {
sideEffectWithData(Seq.empty[String]) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
it should "support SCollection of String over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinStringSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(21)("a")) { in =>
in.closeAndDisplay()
}
}
o.size should be > testRowLimit
o.head should be(stringHeader)
o.last should be(rowLimitReached)
}
// -----------------------------------------------------------------------------------------------
// KV SCollection Tests
// -----------------------------------------------------------------------------------------------
private val kvHeader = s"$table key${tab}value"
it should "support KV (ints) SCollection" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinKVSCollection
val o = captureOut {
sideEffectWithData(Seq((1,2), (3,4))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(kvHeader,
s"3${tab}4",
s"1${tab}2")
o.head should be (kvHeader)
}
it should "support KV (str keys) SCollection" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinKVSCollection
val o = captureOut {
sideEffectWithData(Seq(("foo",2), ("bar",4))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(kvHeader,
s"foo${tab}2",
s"bar${tab}4")
o.head should be (kvHeader)
}
it should "support KV (str values) SCollection" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinKVSCollection
val o = captureOut {
sideEffectWithData(Seq((2,"foo"), (4,"bar"))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs Seq(kvHeader,
s"2${tab}foo",
s"4${tab}bar")
o.head should be (kvHeader)
}
it should "support empty KV SCollection" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinKVSCollection
captureOut {
sideEffectWithData(Seq.empty[(Int, Int)]) { in =>
in.closeAndDisplay()
}
} should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
it should "support SCollection of KV over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinKVSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(21)(("foo", 1))) { in =>
in.closeAndDisplay()
}
}
o.size should be > testRowLimit
o.head should be(kvHeader)
o.last should be(rowLimitReached)
}
// -----------------------------------------------------------------------------------------------
// Product SCollection Tests
// -----------------------------------------------------------------------------------------------
private val testCaseClassHeader = s"$table foo${tab}bar${tab}a"
it should "support SCollection of Tuple of 3" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
val tupleHeader = s"$table _1${tab}_2${tab}_3"
val o = captureOut {
sideEffectWithData(Seq.fill(3)((1,2,3))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(tupleHeader) ++ Seq.fill(3)(s"1${tab}2${tab}3"))
o.head should be(tupleHeader)
}
it should "support SCollection of Tuple of 22" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
val tupleHeader = s"$table " + (1 to 21).map(i => s"_$i$tab").mkString + "_22"
val o = captureOut {
sideEffectWithData(
Seq.fill(3)((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(tupleHeader) ++
Seq.fill(3)((1 to 21).map(i => s"$i$tab").mkString + "22"))
o.head should be(tupleHeader)
}
it should "support SCollection of Case Class of 22" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
val tupleHeader = s"$table " + (1 to 21).map(i => s"a$i$tab").mkString + "a22"
val o = captureOut {
sideEffectWithData(
Seq.fill(3)(CC22(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(tupleHeader) ++
Seq.fill(3)((1 to 21).map(i => s"$i$tab").mkString + "22"))
o.head should be(tupleHeader)
}
it should "support SCollection of Case Class" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(3)(TestCaseClass(1, "foo", 2.0D))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(testCaseClassHeader) ++
Seq.fill(3)(s"1${tab}foo${tab}2.0"))
o.head should be(testCaseClassHeader)
}
it should "support empty SCollection of Product" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
captureOut {
sideEffectWithData(Seq.empty[Product]) { in =>
in.closeAndDisplay()
}
} should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
it should "support SCollection of Product over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinProductSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(21)(TestCaseClass(1, "foo", 2.0D))) { in =>
in.closeAndDisplay()
}
}
o.size should be > testRowLimit
o.head should be(testCaseClassHeader)
o.last should be(rowLimitReached)
}
// -----------------------------------------------------------------------------------------------
// Avro SCollection Tests
// -----------------------------------------------------------------------------------------------
import scala.collection.JavaConverters._
private val schema = {
def f(name: String, tpe: Schema.Type) =
new Schema.Field(
name,
Schema.createUnion(List(Schema.create(Schema.Type.NULL), Schema.create(tpe)).asJava),
null, null)
val s = Schema.createRecord("GenericAccountRecord", null, null, false)
s.setFields(List(
f("id", Schema.Type.INT),
f("amount", Schema.Type.DOUBLE),
f("name", Schema.Type.STRING),
f("type", Schema.Type.STRING)
).asJava)
s
}
private def getTestGenericAvro(i: Int): GenericRecord = {
val s: Schema = new Parser().parse(schema.toString)
val r = new GenericData.Record(s)
r.put("id", i)
r.put("amount", i.toDouble)
r.put("name", "user" + i)
r.put("type", "checking")
r
}
private def getTestAccountAvro(): Account = {
Account.newBuilder()
.setId(2)
.setAmount(2.0D)
.setName("user2")
.setType("checking")
.build()
}
private val avroGenericRecordHeader = s"$table id${tab}amount${tab}name${tab}type"
private val avroAccountHeader = s"$table id${tab}type${tab}name${tab}amount"
it should "support SCollection of GenericRecord" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinAvroSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(3)(getTestGenericAvro(1))) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(avroGenericRecordHeader) ++
Seq.fill(3)(s"1${tab}1.0${tab}user1${tab}checking"))
o.head should be(avroGenericRecordHeader)
}
it should "support SCollection of SpecificRecord Avro" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinAvroSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(3)(getTestAccountAvro())) { in =>
in.closeAndDisplay()
}
}
o should contain theSameElementsAs (Seq(avroAccountHeader) ++
Seq.fill(3)(s"2${tab}checking${tab}user2${tab}2.0"))
o.head should be(avroAccountHeader)
}
it should "support empty SCollection of SpecificRecord Avro" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinAvroSCollection
captureOut {
sideEffectWithData(Seq.empty[Account]) { in =>
in.closeAndDisplay()
}
} should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
it should "support empty SCollection of GenericRecord Avro" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinAvroSCollection
captureOut {
sideEffectWithData(Seq.empty[GenericRecord]) { in =>
in.closeAndDisplay()
}
} should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
it should "support SCollection of GenericRecord Avro over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinAvroSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(21)(getTestGenericAvro(1))) { in =>
in.closeAndDisplay()
}
}
o.size should be > testRowLimit
o.head should be(avroGenericRecordHeader)
o.last should be(rowLimitReached)
}
it should "support SCollection of SpecificRecord Avro over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinAvroSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(21)(getTestAccountAvro())) { in =>
in.closeAndDisplay()
}
}
o.size should be > testRowLimit
o.head should be(avroAccountHeader)
o.last should be(rowLimitReached)
}
// -----------------------------------------------------------------------------------------------
// TableRow SCollection Tests
// -----------------------------------------------------------------------------------------------
private val bQSchema = new TableSchema().setFields(List(
new TableFieldSchema().setName("id").setType("INTEGER"),
new TableFieldSchema().setName("amount").setType("FLOAT"),
new TableFieldSchema().setName("type").setType("STRING"),
new TableFieldSchema().setName("name").setType("STRING")
).asJava)
private val bQHeader = s"$table id${tab}amount${tab}type${tab}name"
private def getBQTableRow(): TableRow = {
TableRow("id" -> 3, "amount" -> 3.0D, "type" -> "checking", "name" -> "user3")
}
it should "support SCollection of TableRow" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinBQTableSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(3)(getBQTableRow())) { in =>
in.closeAndDisplay(bQSchema)
}
}
o should contain theSameElementsAs (Seq(bQHeader) ++
Seq.fill(3)(s"3${tab}3.0${tab}checking${tab}user3"))
o.head should be(bQHeader)
}
it should "print error on empty BQ schema" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinBQTableSCollection
captureOut {
sideEffectWithData(Seq.fill(3)(getBQTableRow())) { in =>
in.closeAndDisplay(new TableSchema())
}
} should contain theSameElementsAs DisplayHelpers.bQSchemaIncomplete.split(newline)
}
it should "support SCollection of TableRow over row limit" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinBQTableSCollection
val o = captureOut {
sideEffectWithData(Seq.fill(21)(getBQTableRow())) { in =>
in.closeAndDisplay(bQSchema)
}
}
o.size should be > testRowLimit
o.head should be(bQHeader)
o.last should be(rowLimitReached)
}
it should "support empty SCollection of TableRow" in {
import org.apache.zeppelin.scio.DisplaySCollectionImplicits.ZeppelinBQTableSCollection
captureOut {
sideEffectWithData(Seq.empty[TableRow]) { in =>
in.closeAndDisplay(new TableSchema())
}
} should contain theSameElementsAs DisplayHelpers.sCollectionEmptyMsg.split(newline)
}
}

View file

@ -0,0 +1,24 @@
/*
* 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.scio
case class TestCaseClass(foo: Int, bar: String, a: Double)
case class CC22(a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int, a7: Int, a8: Int, a9: Int,
a10: Int, a11: Int, a12: Int, a13: Int, a14: Int, a15: Int, a16: Int, a17: Int,
a18: Int, a19: Int, a20: Int, a21: Int, a22: Int)

View file

@ -0,0 +1,50 @@
/*
* 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.scio.util
import java.io.{ByteArrayOutputStream, PrintStream}
import com.google.common.base.Charsets
import com.spotify.scio.ScioContext
import com.spotify.scio.values.SCollection
import org.apache.zeppelin.scio.DisplayHelpers
import scala.reflect.ClassTag
object TestUtils {
val tab = DisplayHelpers.tab
val newline = DisplayHelpers.newline
val table = DisplayHelpers.table
val rowLimitReached = DisplayHelpers.rowLimitReachedMsg.replaceAll(newline,"")
private[scio] def sideEffectWithData[T: ClassTag](data: Iterable[T])
(fn: SCollection[T] => Unit): Unit = {
val sc = ScioContext()
fn(sc.parallelize(data))
if (!sc.isClosed) sc.close()
}
private[scio] def captureOut[T](body: => T): Seq[String] = {
val bytes = new ByteArrayOutputStream()
val stream = new PrintStream(bytes)
Console.withOut(stream) { body }
bytes.toString(Charsets.UTF_8.toString).split(DisplayHelpers.newline)
}
}

View file

@ -320,6 +320,9 @@
<forkCount>1</forkCount>
<reuseForks>false</reuseForks>
<argLine>-Xmx1024m -XX:MaxPermSize=256m</argLine>
<excludes>
<exclude>**/SparkRInterpreterTest.java</exclude>
</excludes>
</configuration>
</plugin>
@ -389,6 +392,12 @@
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<configuration>
<excludes>
<exclude>**/ZeppelinR.scala</exclude>
<exclude>**/SparkRBackend.scala</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>compile</id>
@ -427,25 +436,6 @@
</testExcludes>
</configuration>
</plugin>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/ZeppelinR.scala</exclude>
<exclude>**/SparkRBackend.scala</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/SparkRInterpreterTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

View file

@ -49,6 +49,7 @@ import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.InterpreterHookRegistry.HookType;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.interpreter.util.InterpreterOutputStream;
import org.apache.zeppelin.spark.dep.SparkDependencyContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -65,7 +66,7 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
private GatewayServer gatewayServer;
private DefaultExecutor executor;
private int port;
private SparkOutputStream outputStream;
private InterpreterOutputStream outputStream;
private BufferedWriter ins;
private PipedInputStream in;
private ByteArrayOutputStream input;
@ -190,7 +191,7 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
cmd.addArgument(Integer.toString(port), false);
cmd.addArgument(Integer.toString(getSparkInterpreter().getSparkVersion().toNumber()), false);
executor = new DefaultExecutor();
outputStream = new SparkOutputStream(logger);
outputStream = new InterpreterOutputStream(logger);
PipedOutputStream ps = new PipedOutputStream();
in = null;
try {
@ -440,13 +441,13 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
statementSetNotifier.notify();
}
String[] completionList = null;
synchronized (statementFinishedNotifier) {
long startTime = System.currentTimeMillis();
while (statementOutput == null
&& pythonScriptInitialized == false
&& pythonscriptRunning) {
try {
if (System.currentTimeMillis() - startTime < MAX_TIMEOUT_SEC * 1000) {
if (System.currentTimeMillis() - startTime > MAX_TIMEOUT_SEC * 1000) {
logger.error("pyspark completion didn't have response for {}sec.", MAX_TIMEOUT_SEC);
break;
}
@ -457,16 +458,20 @@ public class PySparkInterpreter extends Interpreter implements ExecuteResultHand
return new LinkedList<>();
}
}
if (statementError) {
return new LinkedList<>();
}
InterpreterResult completionResult;
completionResult = new InterpreterResult(Code.SUCCESS, statementOutput);
Gson gson = new Gson();
completionList = gson.fromJson(completionResult.message(), String[].class);
}
if (statementError) {
return new LinkedList<>();
}
InterpreterResult completionResult = new InterpreterResult(Code.SUCCESS, statementOutput);
//end code for completion
Gson gson = new Gson();
String[] completionList = gson.fromJson(completionResult.message(), String[].class);
if (completionList == null) {
return new LinkedList<>();
}
List<InterpreterCompletion> results = new LinkedList<>();
for (String name: completionList) {
results.add(new InterpreterCompletion(name, name));

View file

@ -49,6 +49,9 @@ import org.apache.spark.ui.jobs.JobProgressListener;
import org.apache.zeppelin.interpreter.*;
import org.apache.zeppelin.interpreter.InterpreterResult.Code;
import org.apache.zeppelin.interpreter.thrift.RemoteZeppelinServerController;
import org.apache.zeppelin.interpreter.InterpreterUtils;
import org.apache.zeppelin.interpreter.WrappedInterpreter;
import org.apache.zeppelin.interpreter.util.InterpreterOutputStream;
import org.apache.zeppelin.resource.ResourcePool;
import org.apache.zeppelin.resource.WellKnownResourceName;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
@ -104,7 +107,7 @@ public class SparkInterpreter extends Interpreter {
private static Integer sharedInterpreterLock = new Integer(0);
private static AtomicInteger numReferenceOfSparkContext = new AtomicInteger(0);
private SparkOutputStream out;
private InterpreterOutputStream out;
private SparkDependencyResolver dep;
private RemoteWorksController remoteWorksController;
@ -122,7 +125,7 @@ public class SparkInterpreter extends Interpreter {
public SparkInterpreter(Properties property) {
super(property);
out = new SparkOutputStream(logger);
out = new InterpreterOutputStream(logger);
}
public SparkInterpreter(Properties property, SparkContext sc) {

View file

@ -22,6 +22,7 @@ import org.apache.commons.io.IOUtils;
import org.apache.zeppelin.interpreter.InterpreterException;
import org.apache.zeppelin.interpreter.InterpreterOutput;
import org.apache.zeppelin.interpreter.InterpreterOutputListener;
import org.apache.zeppelin.interpreter.util.InterpreterOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -38,7 +39,7 @@ public class ZeppelinR implements ExecuteResultHandler {
private final String rCmdPath;
private final SparkVersion sparkVersion;
private DefaultExecutor executor;
private SparkOutputStream outputStream;
private InterpreterOutputStream outputStream;
private PipedOutputStream input;
private final String scriptPath;
private final String libPath;
@ -146,7 +147,7 @@ public class ZeppelinR implements ExecuteResultHandler {
logger.debug(cmd.toString());
executor = new DefaultExecutor();
outputStream = new SparkOutputStream(logger);
outputStream = new InterpreterOutputStream(logger);
input = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(input);

View file

@ -25,6 +25,7 @@ import org.apache.zeppelin.interpreter.InterpreterGroup;
import org.apache.zeppelin.interpreter.InterpreterOutputListener;
import org.apache.zeppelin.interpreter.InterpreterOutput;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.resource.LocalResourcePool;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.junit.After;
@ -37,6 +38,7 @@ import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;
import static org.junit.Assert.*;
@ -144,4 +146,11 @@ public class PySparkInterpreterTest {
}
}
@Test
public void testCompletion() {
if (getSparkVersionNumber() > 11) {
List<InterpreterCompletion> completions = pySparkInterpreter.completion("sc.", "sc.".length());
assertTrue(completions.size() > 0);
}
}
}

View file

@ -1,13 +1,9 @@
The following components are provided under Apache License.
(Apache 2.0) nvd3.js v1.7.1 (http://nvd3.org/) - https://github.com/novus/nvd3/blob/v1.7.1/LICENSE.md
(Apache 2.0) gson v2.2 (com.google.code.gson:gson:jar:2.2 - https://github.com/google/gson) - https://github.com/google/gson/blob/gson-2.2/LICENSE
(Apache 2.0) Amazon Web Services SDK for Java v1.10.62 (https://aws.amazon.com/sdk-for-java/) - https://raw.githubusercontent.com/aws/aws-sdk-java/1.10.62/LICENSE.txt
(Apache 2.0) JavaEWAH v0.7.9 (https://github.com/lemire/javaewah) - https://github.com/lemire/javaewah/blob/master/LICENSE-2.0.txt
The following components are provided under Apache License.
(Apache 2.0) Apache Commons Logging (commons-logging:commons-logging:1.1.1 - http://commons.apache.org/proper/commons-logging/)
(Apache 2.0) Apache Commons Codec (commons-codec:commons-codec:1.5 - http://commons.apache.org/proper/commons-codec/)
(Apache 2.0) Apache Commons Collections (commons-collections:commons-collections:3.2.1 - http://commons.apache.org/proper/commons-configuration/)
@ -19,7 +15,7 @@ The following components are provided under Apache License.
(Apache 2.0) Http Components (org.apache.httpcomponents:httpclient:4.3.6 - https://github.com/apache/httpclient)
(Apache 2.0) Apache Commons Lang (org.apache.commons:commons-lang:2.5 - http://commons.apache.org/proper/commons-lang/)
(Apache 2.0) Apache Commons Lang 3 (org.apache.commons:commons-lang3:3.4 - http://commons.apache.org/proper/commons-lang/)
(Apache 2.0) Apache Commons Math 3 (org.apache.commons:commons-math3:3.4.1 - http://commons.apache.org/proper/commons-math/)
(Apache 2.0) Apache Commons Math 3 (org.apache.commons:commons-math3:3.6.1 - http://commons.apache.org/proper/commons-math/)
(Apache 2.0) Apache Commons Net (commons-net:commons-net:2.2 - http://commons.apache.org/proper/commons-net/)
(Apache 2.0) Apache log4j (log4j:log4j:1.2.17 - http://logging.apache.org/log4j/1.2/)
(Apache 2.0) Apache Commons Pool2 (commons-exec:commons-pool2:2.3 - https://commons.apache.org/proper/commons-pool/)
@ -43,17 +39,24 @@ The following components are provided under Apache License.
(Apache 2.0) Apache Lens (http://lens.apache.org/)
(Apache 2.0) Apache Flink (http://flink.apache.org/)
(Apache 2.0) Apache Beam (http://beam.apache.org/)
(Apache 2.0) Apache Thrift (http://thrift.apache.org/)
(Apache 2.0) Apache Thrift 0.9.2 (org.apache.thrift:libthrift:0.9.2 - http://thrift.apache.org/)
(Apache 2.0) Apache Lucene (https://lucene.apache.org/)
(Apache 2.0) Apache Zookeeper (org.apache.zookeeper:zookeeper:jar:3.4.5 - http://zookeeper.apache.org/)
(Apache 2.0) Chill (com.twitter:chill-java:jar:0.8.0 - https://github.com/twitter/chill/)
(Apache 2.0) Chill (com.twitter:chill:0.8.0 - https://github.com/twitter/chill/)
(Apache 2.0) Chill Java (com.twitter:chill-java:jar:0.8.0 - https://github.com/twitter/chill/)
(Apache 2.0) Chill Protobuf (com.twitter:chill-protobuf:0.8.0 - https://github.com/twitter/chill/)
(Apache 2.0) QDox (com.thoughtworks.qdox:qdox:jar:2.0-M3 - https://github.com/paul-hammant/qdox/)
(Apache 2.0) Codehaus Plexus (org.codehaus.plexus:plexus:jar:1.5.6 - https://codehaus-plexus.github.io/)
(Apache 2.0) Codehaus Plexus Interpolation (org.codehaus.plexus:plexus-interpolation:1.14 - https://codehaus-plexus.github.io/)
(Apache 2.0) Codehaus Plexus Component Annotations (org.codehaus.plexus:plexus-component-annotations:1.5.5 - https://codehaus-plexus.github.io/)
(Apache 2.0) Codehaus Plexus Classwords (org.codehaus.plexus:plexus-classwords:2.4 - https://codehaus-plexus.github.io/)
(Apache 2.0) Codehaus Plexus Utils (org.codehaus.plexus:plexus-utils:2.0.7 - https://codehaus-plexus.github.io/)
(Apache 2.0) findbugs jsr305 (com.google.code.findbugs:jsr305:jar:1.3.9 - http://findbugs.sourceforge.net/)
(Apache 2.0) Google Guava (com.google.guava:guava:15.0 - https://code.google.com/p/guava-libraries/)
(Apache 2.0) Jackson (com.fasterxml.jackson.core:jackson-core:2.5.3 - https://github.com/FasterXML/jackson-core)
(Apache 2.0) Jackson (com.fasterxml.jackson.core:jackson-annotations:2.5.3 - https://github.com/FasterXML/jackson-core)
(Apache 2.0) Jackson (com.fasterxml.jackson.core:jackson-databind:2.5.3 - https://github.com/FasterXML/jackson-core)
(Apache 2.0) Jackson (com.fasterxml.jackson.core:jackson-core:2.7.0 - https://github.com/FasterXML/jackson-core)
(Apache 2.0) Jackson (com.fasterxml.jackson.core:jackson-annotations:2.7.0 - https://github.com/FasterXML/jackson-core)
(Apache 2.0) Jackson (com.fasterxml.jackson.core:jackson-databind:2.7.0 - https://github.com/FasterXML/jackson-core)
(Apache 2.0) Jackson Mapper ASL (org.codehaus.jackson:jackson-mapper-asl:1.9.13 - https://mvnrepository.com/artifact/org.codehaus.jackson/jackson-mapper-asl/1.9.13)
(Apache 2.0) javax.servlet (org.eclipse.jetty.orbit:javax.servlet:jar:3.1.0.v201112011016 - http://www.eclipse.org/jetty)
(Apache 2.0) Joda-Time (joda-time:joda-time:2.8.1 - http://www.joda.org/joda-time/)
(Apache 2.0) Jackson (org.codehaus.jackson:jackson-core-asl:1.9.13 - http://jackson.codehaus.org/)
@ -92,7 +95,7 @@ The following components are provided under Apache License.
(Apache 2.0) Lucene Spatial 3D (org.apache.lucene:lucene-spatial3d:5.3.1 - http://lucene.apache.org/lucene-parent/lucene-spatial3d)
(Apache 2.0) Lucene Suggest (org.apache.lucene:lucene-suggest:5.3.1 - http://lucene.apache.org/lucene-parent/lucene-suggest)
(Apache 2.0) Elasticsearch: Core (org.elasticsearch:elasticsearch:2.1.0 - http://nexus.sonatype.org/oss-repository-hosting.html/parent/elasticsearch)
(Apache 2.0) Joda convert (org.joda:joda-convert:1.2 - http://joda-convert.sourceforge.net)
(Apache 2.0) Joda convert (org.joda:joda-convert:1.8.1 - http://joda-convert.sourceforge.net)
(Apache 2.0) Shiro Core (org.apache.shiro:shiro-core:1.2.3 - https://shiro.apache.org)
(Apache 2.0) Shiro Web (org.apache.shiro:shiro-web:1.2.3 - https://shiro.apache.org)
(Apache 2.0) SnakeYAML (org.yaml:snakeyaml:1.15 - http://www.snakeyaml.org)
@ -121,9 +124,10 @@ The following components are provided under Apache License.
(Apache 2.0) parboiled-core (org.parboiled:parboiled-core:1.1.7 - https://github.com/sirthias/parboiled)
(Apache 2.0) ZkClient (com.101tec:zkclient:0.7 - https://github.com/sgroschupf/zkclient)
(Apache 2.0) jackson-module-scala (com.fasterxml.jackson.module:jackson-module-scala_2.10:2.4.4 - http://wiki.fasterxml.com/JacksonModuleScala)
(Apache 2.0) BigQuery API v2-rev295-1.22.0 (com.google.apis:google-api-services-bigquery:v2-rev295-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-bigquery)
(Apache 2.0) BigQuery API v2-rev317-1.22.0 (com.google.apis:google-api-services-bigquery:v2-rev317-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-bigquery)
(Apache 2.0) Google Cloud Debugger API v2-rev8-1.22.0 (com.google.apis:google-api-services-clouddebugger:v2-rev8-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-clouddebugger)
(Apache 2.0) Google Dataflow API v1b3-rev30-1.22.0 (com.google.apis:google-api-services-dataflow:v1b3-rev30-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-dataflow)
(Apache 2.0) Google Dataflow API v1b3-rev36-1.22.0 (com.google.apis:google-api-services-dataflow:v1b3-rev36-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-dataflow)
(Apache 2.0) Google Dataflow SDK 1.7.0 (com.google.cloud.dataflow:google-cloud-dataflow-java-sdk-all:1.7.0 - https://github.com/GoogleCloudPlatform/DataflowJavaSDK)
(Apache 2.0) Google Cloud Pub/Sub API v1-rev10-1.22.0 (com.google.apis:google-api-services-pubsub:v1-rev10-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-pubsub)
(Apache 2.0) Cloud Storage JSON API v1-rev71-1.22.0 (com.google.apis:google-api-services-storage:v1-rev71-1.22.0 - http://nexus.sonatype.org/oss-repository-hosting.html/google-api-services-storage)
(Apache 2.0) gcsio.jar (com.google.cloud.bigdataoss:gcsio:1.4.5 - https://github.com/GoogleCloudPlatform/BigData-interop/gcsio/)
@ -165,6 +169,52 @@ The following components are provided under Apache License.
(Apache 2.0) tez-yarn-timeline-history-with-acls (org.apache.tez:tez-yarn-timeline-history-with-acls:0.7.0 - http://tez.apache.org)
(Apache 2.0) jna (net.java.dev.jna:jna:4.1.0 https://github.com/java-native-access/jna)
(Apache 2.0) MathJax v2.7.0 - https://github.com/mathjax/MathJax/blob/2.7.0/LICENSE
(Apache 2.0) Scio REPL 0.2.4 (com.spotify:scio-repl:0.2.4 - https://github.com/spotify/scio)
(Apache 2.0) Scio BigQuery 0.2.4 (com.spotify:scio-bigquery:0.2.4 - https://github.com/spotify/scio)
(Apache 2.0) Scio Core 0.2.4 (com.spotify:scio-core:0.2.4 - https://github.com/spotify/scio)
(Apache 2.0) Scio Extra 0.2.4 (com.spotify:scio-extra:0.2.4 - https://github.com/spotify/scio)
(Apache 2.0) Scio Test 0.2.4 (com.spotify:scio-test:0.2.4 - https://github.com/spotify/scio)
(Apache 2.0) Netty Http2 Codec 4.1.0.CR1 (io.netty:netty-codec-http2:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Http Codec 4.1.0.CR1 (io.netty:netty-codec-http:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Handler 4.1.0.CR1 (io.netty:netty-handler:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Buffer 4.1.0.CR1 (io.netty:netty-buffer:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Common 4.1.0.CR1 (io.netty:netty-common:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Transport 4.1.0.CR1 (io.netty:netty-transport:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Resolver 4.1.0.CR1 (io.netty:netty-resolver:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Netty Codec 4.1.0.CR1 (io.netty:netty-codec:4.1.0.CR1 - https://github.com/netty/netty)
(Apache 2.0) Pubsub v1 GRPC Proto 0.0.2 (com.google.api.grpc:grpc-pubsub-v1:0.0.2 - https://github.com/googleapis/googleapis)
(Apache 2.0) Core GRPC Proto 0.0.3 (com.google.api.grpc:grpc-core-proto:0.0.3 - https://github.com/googleapis/googleapis)
(Apache 2.0) Bigtable Proto 0.3.0 (com.google.cloud.bigtable:bigtable-protos:0.3.0 - https://github.com/googleapis/googleapis)
(Apache 2.0) Java Google API Client 1.22.0 (com.google.api-client:google-api-client:1.22.0 - https://github.com/googleapis/googleapis)
(Apache 2.0) Java6 Google API Client 1.22.0 (com.google.api-client:google-api-client-java6:1.22.0 - https://github.com/googleapis/googleapis)
(Apache 2.0) Jackson2 Google API Client 1.22.0 (com.google.api-client:google-api-client-jackson2:1.22.0 - https://github.com/googleapis/googleapis)
(Apache 2.0) Google HTTP Client 1.22.0 (com.google.http-client:google-http-client:1.22.0 - https://github.com/google/google-http-java-client)
(Apache 2.0) Jackson Google HTTP Client 1.22.0 (com.google.http-client:google-http-client-jackson:1.22.0 - https://github.com/google/google-http-java-client)
(Apache 2.0) Jackson2 Google HTTP Client 1.22.0 (com.google.http-client:google-http-client-jackson2:1.22.0 - https://github.com/google/google-http-java-client)
(Apache 2.0) Protobuf Google HTTP Client 1.22.0 (com.google.http-client:google-http-client-protobuf:1.22.0 - https://github.com/google/google-http-java-client)
(Apache 2.0) Google OAuth Java6 Client 1.22.0 (com.google.oauth-client:google-oauth-client-java6:1.22.0 - https://github.com/google/google-oauth-java-client)
(Apache 2.0) Google OAuth Client 1.22.0 (com.google.oauth-client:google-oauth-client:1.22.0 - https://github.com/google/google-oauth-java-client)
(Apache 2.0) Google API Datastore Protobuf v1beta2-rev1-4.0.0 (com.google.apis:google-api-services-datastore-protobuf:v1beta2-rev1-4.0.0 - https://github.com/googleapis/googleapis)
(Apache 2.0) Google Datastore v1 Protobuf Client 1.1.0 (com.google.cloud.datastore:datastore-v1-proto-client:1.1.0 - https://github.com/GoogleCloudPlatform/google-cloud-datastore)
(Apache 2.0) Google Datastore v1 Protos 1.0.1 (com.google.cloud.datastore:datastore-v1-protos:1.0.1 - https://github.com/googleapis/googleapis)
(Apache 2.0) Twitter Algebird 0.12.1 (com.twitter:algebird-core:0.12.1 - https://github.com/twitter/algebird)
(Apache 2.0) Breeze 0.12 (org.scalanlp:breeze:0.12 - https://github.com/scalanlp/breeze)
(Apache 2.0) Breeze Macros 0.12 (org.scalanlp:breeze-macros:0.12 - https://github.com/scalanlp/breeze)
(Apache 2.0) Opencsv 2.3 (net.sf.opencsv:opencsv:2.3 - http://opencsv.sourceforge.net/)
(Apache 2.0) Shapeless 2.0.0 (com.chuusai:shapeless:2.0.0 - https://github.com/milessabin/shapeless)
(Apache 2.0) Katan CSV 0.1.12 (com.nrinaudo:kantan.csv:0.1.12 - https://github.com/nrinaudo/kantan.csv)
(Apache 2.0) Katan Codecs 0.1.6 (com.nrinaudo:kantan.codecs:0.1.6 - https://github.com/nrinaudo/kantan.csv)
(Apache 2.0) jansi 1.4 (org.fusesource.jansi:jansi:1.4 - https://github.com/fusesource/jansi)/
(Apache 2.0) Maven Plugin API 3.0 (org.apache.maven:maven-plugin-api:3.0 - https://github.com/apache/maven)
(Apache 2.0) Maven Artifact 3.0 (org.apache.maven:maven-artifact:3.0 - https://github.com/apache/maven)
(Apache 2.0) Maven Model Builder 3.0.3 (org.apache.maven:maven-model-builder:3.0.3 - https://github.com/apache/maven)
(Apache 2.0) Maven Repository Metadata 3.0.3 (org.apache.maven:maven-repository-metadata:3.0.3 - https://github.com/apache/maven)
(Apache 2.0) Maven Wagon Provider API 1.0 (org.apache.maven.wagon:wagon-provider-api:1.0 - https://mvnrepository.com/artifact/org.apache.maven.wagon/wagon-provider-api/1.0)
(Apache 2.0) Maven Wagon HTTP Lightweight 1.0 (org.apache.maven.wagon:wagon-http-lightweight:1.0 - https://mvnrepository.com/artifact/org.apache.maven.wagon/wagon-http-lightweight/1.0)
(Apache 2.0) Maven Wagon HTTP 1.0 (org.apache.maven.wagon:wagon-http:1.0 - https://mvnrepository.com/artifact/org.apache.maven.wagon/wagon-http/1.0)
(Apache 2.0) Maven Wagon HTTP Shared 1.0 (org.apache.maven.wagon:wagon-http-shared:1.0 - https://mvnrepository.com/artifact/org.apache.maven.wagon/wagon-http-shared/1.0)
(Apache 2.0) Commons HTTP Client 3.1 (commons-httpclient:commons-httpclient:3.1 - https://mvnrepository.com/artifact/commons-httpclient/commons-httpclient/3.1)
(Apache 2.0) Scalatest 2.2.4 (org.scalatest:scalatest_2.10:2.2.4 - https://github.com/scalatest/scalatest)
========================================================================
MIT licenses
@ -197,14 +247,13 @@ The text of each license is also included at licenses/LICENSE-[project]-[version
(The MIT License) Moment v2.9.0 (https://github.com/moment/moment) - https://github.com/moment/moment/blob/2.9.0/LICENSE
(The MIT License) Pikaday v1.3.2 (https://github.com/dbushell/Pikaday) - https://github.com/dbushell/Pikaday/blob/1.3.2/LICENSE
(The MIT License) slf4j v1.7.10 (org.slf4j:slf4j-api:jar:1.7.10 - http://www.slf4j.org) - http://www.slf4j.org/license.html
(The MIT License) slf4j v1.7.21 (org.slf4j:slf4j-simple:1.7.21 - http://www.slf4j.org) - http://www.slf4j.org/license.html
(The MIT License) slf4j-log4j12 v1.7.10 (org.slf4j:slf4j-log4j12:jar:1.7.10 - http://www.slf4j.org) - http://www.slf4j.org/license.html
(The MIT License) bcprov-jdk15on v1.51 (org.bouncycastle:bcprov-jdk15on:jar:1.51 - http://www.bouncycastle.org/java.html) - http://www.bouncycastle.org/licence.html
(The MIT License) AnchorJS (https://github.com/bryanbraun/anchorjs) - https://github.com/bryanbraun/anchorjs/blob/master/README.md#license
(The MIT License) moment-duration-format v1.3.0 (https://github.com/jsmreese/moment-duration-format) - https://github.com/jsmreese/moment-duration-format/blob/master/LICENSE
(The MIT License) github-markdown-css 2.4.0 (https://github.com/sindresorhus/github-markdown-css) - https://github.com/sindresorhus/github-markdown-css/blob/gh-pages/license
(The MIT License) scopt (com.github.scopt:scopt_2.10:3.2.0 - https://github.com/scopt/scopt)
The following components are provided under the MIT License.
(The MIT License) Objenesis (org.objenesis:objenesis:2.1 - https://github.com/easymock/objenesis) - Copyright (c) 2006-2015 the original author and authors
(The MIT License) JCL 1.1.1 implemented over SLF4J (org.slf4j:jcl-over-slf4j:1.7.16 - http://www.slf4j.org)
(The MIT License) JUL to SLF4J bridge (org.slf4j:jul-to-slf4j:1.7.16 - http://www.slf4j.org)
@ -212,6 +261,11 @@ The following components are provided under the MIT License.
(The MIT License) minimal-json (com.eclipsesource.minimal-json:minimal-json:0.9.4 - https://github.com/ralfstx/minimal-json)
(The MIT License) pyrolite (net.razorvine:pyrolite:4.9) - https://github.com/irmen/Pyrolite/blob/v4.9/LICENSE)
(The MIT License) libpam4j (org.kohsuke:libpam4j:1.8 https://github.com/kohsuke/libpam4j/blob/master/src/main/java/org/jvnet/libpam/PAM.java)
(The MIT License) Spire 0.7.4 (org.spire-math:spire:0.7.4 - https://github.com/non/spire)
(The MIT License) Spire Macros 0.7.4 (org.spire-math:spire-macros:0.7.4 - https://github.com/non/spire)
(The MIT License) Java String Similarity 0.12 (info.debatty:java-string-similarity:0.12 - https://github.com/tdebatty/java-string-similarity)
(The MIT License) Java LSH 0.10 (info.debatty:java-lsh:0.10 - https://github.com/tdebatty/java-LSH)
(The MIT License) JSoup 1.6.1 (org.jsoup:jsoup:1.6.1 - https://github.com/jhy/jsoup/)
========================================================================
BSD-style licenses
@ -242,8 +296,10 @@ The text of each license is also included at licenses/LICENSE-[project]-[version
(BSD 3-Clause) io.grpc:grpc-protobuf-lite (io.grpc:grpc-protobuf-lite:0.14.1 - https://github.com/grpc/grpc-java)
(BSD 3-Clause) io.grpc:grpc-protobuf-nano (io.grpc:grpc-protobuf-nano:0.14.1 - https://github.com/grpc/grpc-java)
(BSD 3-Clause) io.grpc:grpc-stub (io.grpc:grpc-stub:0.14.1 - https://github.com/grpc/grpc-java)
(BSD-3-Clause) Kryo 3.0.3 (com.esotericsoftware:kryo-shaded:3.0.3 - https://github.com/EsotericSoftware/kryo)
(BSD-3-Clause) Minilog 1.3.0 (com.esotericsoftware:minlog:1.3.0 - https://github.com/EsotericSoftware/minlog)
The following components are provided under the BSD-style License.
(New BSD License) JGit (org.eclipse.jgit:org.eclipse.jgit:jar:4.1.1.201511131810-r - https://eclipse.org/jgit/)
@ -275,6 +331,10 @@ The following components are provided under the BSD-style License.
(BSD-style) spire-macros (org.spire-math:spire-macros_2.11:0.7.1 - http://spire-math.org)
(The BSD License) Fortran to Java ARPACK (net.sourceforge.f2j:arpack_combined_all:0.1 - http://f2j.sourceforge.net)
(The BSD License) xmlenc Library (xmlenc:xmlenc:0.52 - http://xmlenc.sourceforge.net)
(BSD-3-Clause) Scalamacros Paradise 2.1.0 (org.scalamacros:paradise6:2.1.0 - https://github.com/scalamacros/paradise)
(BSD-3-Clause) Scalamacros Quasiquotes 2.1.0 (org.scalamacros:quasiquotes:2.1.0 - https://mvnrepository.com/artifact/org.scalamacros/quasiquotes_2.10/2.1.0)
(BSD-2-Clause) JUnit Interface 0.11 (com.novocode:junit-interface:0.11 - https://github.com/sbt/junit-interface)
(BSD-3-Clause) SBT Test Interface (org.scala-sbt:test-interface:1.0 - https://github.com/sbt/test-interface)
========================================================================
CDDL license
@ -291,11 +351,11 @@ The following components are provided under the CDDL License.
(CDDL 1.1) jersey-json (com.sun.jersey:jersey-json:1.9 - https://jersey.java.net/jersey-json/)
(CDDL 1.1) jersey-server (com.sun.jersey:jersey-server:1.9 - https://jersey.java.net/jersey-server/)
(CDDL 1.1) jersey-guice (com.sun.jersey.contribs:jersey-guice:1.9 - https://jersey.java.net/jersey-contribs/jersey-guice/)
(CDDL 1.1) JAXB RI (com.sun.xml.bind:jaxb-impl:2.2.3-1 - http://jaxb.java.net/)
(CDDL 1.1) JAXB RI (com.sun.xml.bind:jaxb-impl:2.2.3-1 - http://jaxb.java.net/)
(CDDL 1.0) Java Servlet API (javax.servlet:javax.servlet-api:3.1.0 - http://servlet-spec.java.net)
(CDDL 1.1) (GPL2 w/ CPE) JAXB API bundle for GlassFish V3 (javax.xml.bind:jaxb-api:2.2.2 - https://jaxb.dev.java.net/)
(CDDL 1.0) (GNU General Public Library) Streaming API for XML (javax.xml.stream:stax-api:1.0-2 - no url defined)
========================================================================
EPL license
@ -306,6 +366,10 @@ The following components are provided under the EPL License.
(EPL 1.0) Aether (org.sonatype.aether - http://www.eclipse.org/aether/)
(EPL 1.0) JDT Annotations For Enhanced Null Analysis (org.eclipse.jdt:org.eclipse.jdt.annotation:1.1.0 - https://repo.eclipse.org/content/repositories/eclipse-releases/org/eclipse/jdt/org.eclipse.jdt.annotation)
(EPL 1.0) JRuby (org.jruby.jruby-complete:v1.6.8 - http://www.jruby.org/)
(EPL 1.0) Sisu Inject Plexus 2.2.2 (org.sonatype.sisu:sisu-inject-plexus:2.2.2 - https://github.com/sonatype/sisu)
(EPL 1.0) Sisu Inject Bean 2.2.2 (org.sonatype.sisu:sisu-inject-bean:2.2.2 - https://github.com/sonatype/sisu)
(EPL 1.0) Sisu Inject Guice (org.sonatype.sisu:sisu-inject-guice:no_aop- https://github.com/sonatype/sisu)
(EPL 1.0) JUnit 4.11 (junit:junit:4.11 - https://github.com/junit-team/junit4)
@ -342,3 +406,8 @@ Creative Commons CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
(Public Domain, per Creative Commons CC0) HdrHistogram (org.hdrhistogram:HdrHistogram:2.1.6 - http://hdrhistogram.github.io/HdrHistogram/)
(Public Domain) XZ for Java (org.tukaani:xz:1.0 - http://tukaani.org/xz/java.html)
(Public Domain) AOP alliance (aopalliance:aopalliance:1.0 - http://aopalliance.sourceforge.net)
========================================================================
Multiple licenses
========================================================================
(LGPLv2) (GPLv2) (MPL 1.1) Jtransforms (com.github.rwl:jtransforms:2.4.0 - https://sourceforge.net/projects/jtransforms/)

View file

@ -0,0 +1,7 @@
Copyright 2015 Thibault Debatty.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,7 @@
Copyright 2015 Thibault Debatty.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,21 @@
The MIT License
© 2009-2016, Jonathan Hedley <jonathan@hedley.net>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View file

@ -0,0 +1,33 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is JTransforms.
*
* The Initial Developer of the Original Code is
* Piotr Wendykier, Emory University.
* Portions created by the Initial Developer are Copyright (C) 2007-2009
* the Initial Developer. All Rights Reserved.
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */

View file

@ -0,0 +1,24 @@
Copyright (c) 2009-2012, Stefan Zeiger
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,10 @@
Copyright (c) 2008, Nathan Sweet
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,10 @@
Copyright (c) 2008, Nathan Sweet
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of Esoteric Software nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,25 @@
Copyright (c) 2009, 2010 Josh Cough, Mark Harrah
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,27 @@
Copyright (c) 2013-2015 EPFL
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the EPFL nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,27 @@
Copyright (c) 2013-2015 EPFL
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the EPFL nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,21 @@
Copyright (c) 2004-2013 QOS.ch
All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,19 @@
Copyright (c) 2011-2012 Erik Osheim, Tom Switzer
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,19 @@
Copyright (c) 2011-2012 Erik Osheim, Tom Switzer
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -14,7 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zeppelin.spark;
package org.apache.zeppelin.interpreter.util;
import org.apache.zeppelin.interpreter.InterpreterOutput;
import org.slf4j.Logger;
@ -22,14 +23,15 @@ import org.slf4j.Logger;
import java.io.IOException;
/**
* InterpreterOutput can be attached / detached.
* Output Stream integrated with InterpreterOutput.
*
* Can be used to channel output from interpreters.
*/
public class SparkOutputStream extends LogOutputStream {
public class InterpreterOutputStream extends LogOutputStream {
public static Logger logger;
InterpreterOutput interpreterOutput;
public SparkOutputStream(Logger logger) {
public InterpreterOutputStream(Logger logger) {
this.logger = logger;
}
@ -78,6 +80,7 @@ public class SparkOutputStream extends LogOutputStream {
}
}
@Override
public void flush() throws IOException {
super.flush();

View file

@ -15,13 +15,12 @@
* limitations under the License.
*/
package org.apache.zeppelin.spark;
package org.apache.zeppelin.interpreter.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Minor modification of LogOutputStream of apache commons exec.
* LogOutputStream of apache commons exec has one issue that method flush doesn't throw IOException,

View file

@ -19,6 +19,7 @@ package org.apache.zeppelin.rest;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.apache.zeppelin.annotation.ZeppelinApi;
import org.apache.zeppelin.notebook.NotebookAuthorization;
import org.apache.zeppelin.server.JsonResponse;
import org.apache.zeppelin.ticket.TicketContainer;
import org.apache.zeppelin.utils.SecurityUtils;
@ -89,6 +90,9 @@ public class LoginRestApi {
response = new JsonResponse(Response.Status.OK, "", data);
//if no exception, that's it, we're done!
//set roles for user in NotebookAuthorization module
NotebookAuthorization.getInstance().setRoles(principal, roles);
} catch (UnknownAccountException uae) {
//username wasn't in the system, show them an error message?
LOG.error("Exception in login: ", uae);

View file

@ -258,8 +258,10 @@ public class NotebookRestApi {
@ZeppelinApi
public Response getNoteList() throws IOException {
AuthenticationInfo subject = new AuthenticationInfo(SecurityUtils.getPrincipal());
HashSet<String> userAndRoles = SecurityUtils.getRoles();
userAndRoles.add(subject.getUser());
List<Map<String, String>> notesInfo = notebookServer.generateNotesInfo(false, subject,
SecurityUtils.getRoles());
userAndRoles);
return new JsonResponse<>(Status.OK, "", notesInfo).build();
}

View file

@ -48,13 +48,7 @@ import org.apache.zeppelin.interpreter.InterpreterSetting;
import org.apache.zeppelin.interpreter.remote.RemoteAngularObjectRegistry;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterProcessListener;
import org.apache.zeppelin.interpreter.thrift.InterpreterCompletion;
import org.apache.zeppelin.notebook.JobListenerFactory;
import org.apache.zeppelin.notebook.Note;
import org.apache.zeppelin.notebook.Notebook;
import org.apache.zeppelin.notebook.NotebookAuthorization;
import org.apache.zeppelin.notebook.NotebookEventListener;
import org.apache.zeppelin.notebook.Paragraph;
import org.apache.zeppelin.notebook.ParagraphJobListener;
import org.apache.zeppelin.notebook.*;
import org.apache.zeppelin.notebook.repo.NotebookRepo.Revision;
import org.apache.zeppelin.notebook.socket.Message;
import org.apache.zeppelin.notebook.socket.Message.OP;
@ -234,6 +228,9 @@ public class NotebookServer extends WebSocketServlet implements
case NOTE_UPDATE:
updateNote(conn, userAndRoles, notebook, messagereceived);
break;
case NOTE_RENAME:
renameNote(conn, userAndRoles, notebook, messagereceived);
break;
case COMPLETION:
completion(conn, userAndRoles, notebook, messagereceived);
break;
@ -429,9 +426,10 @@ public class NotebookServer extends WebSocketServlet implements
private void multicastToUser(String user, Message m) {
if (!userConnectedSockets.containsKey(user)) {
LOG.warn("Broadcasting to user that is not in connections map");
LOG.warn("Multicasting to user {} that is not in connections map", user);
return;
}
for (NotebookSocket conn: userConnectedSockets.get(user)) {
try {
conn.send(serializeMessage(m));
@ -509,7 +507,7 @@ public class NotebookServer extends WebSocketServlet implements
}
public List<Map<String, String>> generateNotesInfo(boolean needsReload,
AuthenticationInfo subject, HashSet<String> userAndRoles) {
AuthenticationInfo subject, Set<String> userAndRoles) {
Notebook notebook = notebook();
@ -561,13 +559,7 @@ public class NotebookServer extends WebSocketServlet implements
List<Map<String, String>> notesInfo = generateNotesInfo(false, subject, userAndRoles);
multicastToUser(subject.getUser(), new Message(OP.NOTES_INFO).put("notes", notesInfo));
//to others afterwards
for (String user: userConnectedSockets.keySet()) {
if (subject.getUser() == user) {
continue;
}
notesInfo = generateNotesInfo(false, new AuthenticationInfo(user), userAndRoles);
multicastToUser(user, new Message(OP.NOTES_INFO).put("notes", notesInfo));
}
broadcastNoteListExcept(notesInfo, subject);
}
public void unicastNoteList(NotebookSocket conn, AuthenticationInfo subject,
@ -580,20 +572,30 @@ public class NotebookServer extends WebSocketServlet implements
if (subject == null) {
subject = new AuthenticationInfo(StringUtils.EMPTY);
}
//reload and reply first to requesting user
List<Map<String, String>> notesInfo = generateNotesInfo(true, subject, userAndRoles);
multicastToUser(subject.getUser(), new Message(OP.NOTES_INFO).put("notes", notesInfo));
//to others afterwards
broadcastNoteListExcept(notesInfo, subject);
}
private void broadcastNoteListExcept(List<Map<String, String>> notesInfo,
AuthenticationInfo subject) {
Set<String> userAndRoles;
NotebookAuthorization authInfo = NotebookAuthorization.getInstance();
for (String user: userConnectedSockets.keySet()) {
if (subject.getUser() == user) {
if (subject.getUser().equals(user)) {
continue;
}
//reloaded already above; parameter - false
userAndRoles = authInfo.getRoles(user);
userAndRoles.add(user);
notesInfo = generateNotesInfo(false, new AuthenticationInfo(user), userAndRoles);
multicastToUser(user, new Message(OP.NOTES_INFO).put("notes", notesInfo));
}
}
void permissionError(NotebookSocket conn, String op,
String userName,
Set<String> userAndRoles,
@ -701,6 +703,34 @@ public class NotebookServer extends WebSocketServlet implements
}
}
private void renameNote(NotebookSocket conn, HashSet<String> userAndRoles,
Notebook notebook, Message fromMessage)
throws SchedulerException, IOException {
String noteId = (String) fromMessage.get("id");
String name = (String) fromMessage.get("name");
if (noteId == null) {
return;
}
NotebookAuthorization notebookAuthorization = notebook.getNotebookAuthorization();
if (!notebookAuthorization.isOwner(noteId, userAndRoles)) {
permissionError(conn, "renameNote", fromMessage.principal,
userAndRoles, notebookAuthorization.getOwners(noteId));
return;
}
Note note = notebook.getNote(noteId);
if (note != null) {
note.setName(name);
AuthenticationInfo subject = new AuthenticationInfo(fromMessage.principal);
note.persist(subject);
broadcastNote(note);
broadcastNoteList(subject, userAndRoles);
}
}
private boolean isCronUpdated(Map<String, Object> configA,
Map<String, Object> configB) {
boolean cronUpdated = false;

View file

@ -88,6 +88,10 @@
}
});
$scope.renameNote = function(node) {
noteActionSrv.renameNote(node.id, node.path);
};
$scope.removeNote = function(noteId) {
noteActionSrv.removeNote(noteId, false);
};

View file

@ -14,20 +14,26 @@ limitations under the License.
<script type="text/ng-template" id="notebook_folder_renderer.html">
<div ng-if="node.children == null"
ng-mouseenter="showButton=true"
ng-mouseleave="showButton=false">
ng-mouseenter="showNoteButton=true"
ng-mouseleave="showNoteButton=false">
<a style="text-decoration: none;" href="#/notebook/{{node.id}}">
<i style="font-size: 10px;" class="icon-doc"/> {{noteName(node)}}
</a>
<a style="text-decoration: none;">
<i style="font-size: 13px; margin-left: 10px; cursor: pointer; text-decoration: none;"
class="fa fa-eraser" ng-show="showButton" ng-click="clearAllParagraphOutput(node.id)"
class="fa fa-pencil" ng-show="showNoteButton" ng-click="renameNote(node)"
tooltip-placement="bottom" tooltip="Rename note">
</i>
</a>
<a style="text-decoration: none;">
<i style="font-size: 13px; margin-left: 2px; cursor: pointer; text-decoration: none;"
class="fa fa-eraser" ng-show="showNoteButton" ng-click="clearAllParagraphOutput(node.id)"
tooltip-placement="bottom" tooltip="Clear output">
</i>
</a>
<a style="text-decoration: none;">
<i style="font-size: 13px; margin-left: 2px; cursor: pointer; text-decoration: none;"
class="fa fa-trash-o" ng-show="showButton" ng-click="removeNote(node.id)"
class="fa fa-trash-o" ng-show="showNoteButton" ng-click="removeNote(node.id)"
tooltip-placement="bottom" tooltip="Remove note">
</i>
</a>

View file

@ -1850,7 +1850,8 @@
});
$scope.$on('doubleClickParagraph', function(event, paragraphId) {
if ($scope.paragraph.id === paragraphId && editorSetting.editOnDblClick) {
if ($scope.paragraph.id === paragraphId && $scope.paragraph.config.editorHide &&
editorSetting.editOnDblClick) {
var deferred = $q.defer();
openEditorAndCloseTable();
$timeout(

View file

@ -16,9 +16,9 @@
angular.module('zeppelinWebApp').service('noteActionSrv', noteActionSrv);
noteActionSrv.$inject = ['websocketMsgSrv', '$location'];
noteActionSrv.$inject = ['websocketMsgSrv', '$location', 'renameSrv'];
function noteActionSrv(websocketMsgSrv, $location) {
function noteActionSrv(websocketMsgSrv, $location, renameSrv) {
this.removeNote = function(noteId, redirectToHome) {
BootstrapDialog.confirm({
closable: true,
@ -47,5 +47,15 @@
}
});
};
this.renameNote = function(noteId, notePath) {
renameSrv.openRenameModal({
title: 'Rename note',
oldName: notePath,
callback: function(newName) {
websocketMsgSrv.renameNote(noteId, newName);
}
});
};
}
})();

View file

@ -43,7 +43,8 @@
if (nodes.length === 1) { // the leaf
curDir.children.push({
name: nodes[0],
id: noteId
id: noteId,
path: curDir.id ? curDir.id + '/' + nodes[0] : nodes[0]
});
} else { // a folder node
var node = nodes.shift();
@ -53,6 +54,7 @@
addNode(dir, nodes, noteId);
} else {
var newDir = {
id: curDir.id ? curDir.id + '/' + node : node,
name: node,
hidden: true,
children: []

View file

@ -0,0 +1,50 @@
/*
* 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.
*/
'use strict';
(function() {
angular.module('zeppelinWebApp').controller('RenameCtrl', RenameCtrl);
RenameCtrl.$inject = ['$scope'];
function RenameCtrl($scope) {
var self = this;
$scope.params = {newName: ''};
$scope.isValid = true;
$scope.rename = function() {
angular.element('#renameModal').modal('hide');
self.callback($scope.params.newName);
};
$scope.$on('openRenameModal', function(event, options) {
self.validator = options.validator || defaultValidator;
self.callback = options.callback || function() {};
$scope.title = options.title || 'Rename';
$scope.params.newName = options.oldName || '';
$scope.validate = function() {
$scope.isValid = self.validator($scope.params.newName);
};
angular.element('#renameModal').modal('show');
});
function defaultValidator(str) {
return !!str.trim();
}
}
})();

View file

@ -0,0 +1,42 @@
<!--
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="renameModal" class="modal fade" role="dialog"
tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">{{title}}</h4>
</div>
<div class="modal-body">
<label ng-if="isValid">Please enter a new name</label>
<label class="text-danger" ng-if="!isValid">Please enter a valid name</label>
<div class="form-group" ng-class="{'has-error': !isValid}">
<input type="text" class="form-control"
ng-model="params.newName" ng-change="validate()"
ng-keyup="$event.keyCode == 13 && isValid && rename()" />
</div>
</div>
<div class="modal-footer">
<div>
<button type="button" class="btn btn-default btn-primary"
ng-click="rename()" ng-class="{'disabled': !isValid}">
Rename
</button>
</div>
</div>
</div>
</div>
</div>

View file

@ -0,0 +1,35 @@
/*
* 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.
*/
'use strict';
(function() {
angular.module('zeppelinWebApp').service('renameSrv', renameSrv);
renameSrv.$inject = ['$rootScope'];
function renameSrv($rootScope) {
var self = this;
/**
* <options schema>
* title: string - Modal title
* oldName: string - name to initialize input
* callback: (newName: string)=>void - callback onButtonClick
* validator: (str: string)=>boolean - input validator
*/
self.openRenameModal = function(options) {
$rootScope.$broadcast('openRenameModal', options);
};
}
})();

View file

@ -59,6 +59,10 @@
websocketEvents.sendNewEvent({op: 'NOTE_UPDATE', data: {id: noteId, name: noteName, config: noteConfig}});
},
renameNote: function(noteId, noteName) {
websocketEvents.sendNewEvent({op: 'NOTE_RENAME', data: {id: noteId, name: noteName}});
},
moveParagraph: function(paragraphId, newIndex) {
websocketEvents.sendNewEvent({op: 'MOVE_PARAGRAPH', data: {id: paragraphId, index: newIndex}});
},

View file

@ -93,6 +93,9 @@ limitations under the License.
<div ng-controller="LoginCtrl as noteimportctrl">
<div id="login-container" ng-include src="'components/login/login.html'"></div>
</div>
<div ng-controller="RenameCtrl">
<div ng-include src="'components/rename/rename.html'"></div>
</div>
<!-- build:js(.) scripts/oldieshim.js -->
<!--[if lt IE 9]>
<script src="bower_components/es5-shim/es5-shim.js"></script>
@ -212,6 +215,8 @@ limitations under the License.
<script src="components/login/login.controller.js"></script>
<script src="components/elasticInputCtrl/elasticInput.controller.js"></script>
<script src="components/noteAction/noteAction.service.js"></script>
<script src="components/rename/rename.controller.js"></script>
<script src="components/rename/rename.service.js"></script>
<!-- endbuild -->
</body>
</html>

View file

@ -46,7 +46,7 @@ describe('Factory: NoteList', function() {
expect(folderList[1].name).toBe('B');
expect(folderList[2].name).toBe('000003');
expect(folderList[3].name).toBe('C');
expect(folderList[3].id).toBeUndefined();
expect(folderList[3].id).toBe('C');
expect(folderList[3].children.length).toBe(3);
expect(folderList[3].children[0].name).toBe('CA');
expect(folderList[3].children[0].id).toBe('000004');
@ -55,7 +55,7 @@ describe('Factory: NoteList', function() {
expect(folderList[3].children[1].id).toBe('000005');
expect(folderList[3].children[1].children).toBeUndefined();
expect(folderList[3].children[2].name).toBe('CB');
expect(folderList[3].children[2].id).toBeUndefined();
expect(folderList[3].children[2].id).toBe('C/CB');
expect(folderList[3].children[2].children.length).toBe(3);
expect(folderList[3].children[2].children[0].name).toBe('CBA');
expect(folderList[3].children[2].children[0].id).toBe('000006');
@ -67,10 +67,10 @@ describe('Factory: NoteList', function() {
expect(folderList[3].children[2].children[2].id).toBe('000008');
expect(folderList[3].children[2].children[2].children).toBeUndefined();
expect(folderList[4].name).toBe('D');
expect(folderList[4].id).toBeUndefined();
expect(folderList[4].id).toBe('D');
expect(folderList[4].children.length).toBe(1);
expect(folderList[4].children[0].name).toBe('D[A');
expect(folderList[4].children[0].id).toBeUndefined();
expect(folderList[4].children[0].id).toBe('D/D[A');
expect(folderList[4].children[0].children[0].name).toBe('DA]B');
expect(folderList[4].children[0].children[0].id).toBe('000009');
expect(folderList[4].children[0].children[0].children).toBeUndefined();

View file

@ -168,12 +168,6 @@
<version>5.3.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>

View file

@ -544,7 +544,8 @@ public class ZeppelinConfiguration extends XMLConfiguration {
+ "org.apache.zeppelin.jdbc.JDBCInterpreter,"
+ "org.apache.zeppelin.hbase.HbaseInterpreter,"
+ "org.apache.zeppelin.bigquery.BigQueryInterpreter,"
+ "org.apache.zeppelin.beam.BeamInterpreter"),
+ "org.apache.zeppelin.beam.BeamInterpreter,"
+ "org.apache.zeppelin.scio.ScioInterpreter"),
ZEPPELIN_INTERPRETER_JSON("zeppelin.interpreter.setting", "interpreter-setting.json"),
ZEPPELIN_INTERPRETER_DIR("zeppelin.interpreter.dir", "interpreter"),
ZEPPELIN_INTERPRETER_LOCALREPO("zeppelin.interpreter.localRepo", "local-repo"),
@ -552,7 +553,7 @@ public class ZeppelinConfiguration extends XMLConfiguration {
ZEPPELIN_INTERPRETER_MAX_POOL_SIZE("zeppelin.interpreter.max.poolsize", 10),
ZEPPELIN_INTERPRETER_GROUP_ORDER("zeppelin.interpreter.group.order", "spark,md,angular,sh,"
+ "livy,alluxio,file,psql,flink,python,ignite,lens,cassandra,geode,kylin,elasticsearch,"
+ "scalding,jdbc,hbase,bigquery,beam,pig"),
+ "scalding,jdbc,hbase,bigquery,beam,pig,scio"),
ZEPPELIN_ENCODING("zeppelin.encoding", "UTF-8"),
ZEPPELIN_NOTEBOOK_DIR("zeppelin.notebook.dir", "notebook"),
// use specified notebook (id) as homescreen

View file

@ -542,7 +542,7 @@ public class Notebook implements NoteEventListener {
}
}
public List<Note> getAllNotes(HashSet<String> userAndRoles) {
public List<Note> getAllNotes(Set<String> userAndRoles) {
final Set<String> entities = Sets.newHashSet();
if (userAndRoles != null) {
entities.addAll(userAndRoles);

View file

@ -24,6 +24,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@ -32,6 +33,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.user.AuthenticationInfo;
import org.slf4j.Logger;
@ -53,6 +55,10 @@ public class NotebookAuthorization {
* { "note1": { "owners": ["u1"], "readers": ["u1", "u2"], "writers": ["u1"] }, "note2": ... } }
*/
private static Map<String, Map<String, Set<String>>> authInfo = new HashMap<>();
/*
* contains roles for each user
*/
private static Map<String, Set<String>> userRoles = new HashMap<>();
private static ZeppelinConfiguration conf;
private static Gson gson;
private static String filePath;
@ -108,7 +114,24 @@ public class NotebookAuthorization {
NotebookAuthorizationInfoSaving.class);
authInfo = info.authInfo;
}
public void setRoles(String user, Set<String> roles) {
if (StringUtils.isBlank(user)) {
LOG.warn("Setting roles for empty user");
return;
}
roles = validateUser(roles);
userRoles.put(user, roles);
}
public Set<String> getRoles(String user) {
Set<String> roles = Sets.newHashSet();
if (userRoles.containsKey(user)) {
roles.addAll(userRoles.get(user));
}
return roles;
}
private void saveToFile() {
String jsonString;

View file

@ -17,7 +17,6 @@
package org.apache.zeppelin.notebook;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

View file

@ -53,6 +53,8 @@ public class Message {
// @param object notebook
NOTE_UPDATE,
NOTE_RENAME,
RUN_PARAGRAPH, // [c-s] run paragraph
// @param id paragraph id
// @param paragraph paragraph content.ie. script

View file

@ -674,6 +674,48 @@ public class NotebookTest implements JobListenerFactory{
notebook.removeNote(note.getId(), anonymous);
}
@Test
public void testAuthorizationRoles() throws IOException {
String user1 = "user1";
String user2 = "user2";
Set<String> roles = Sets.newHashSet("admin");
// set admin roles for both user1 and user2
notebookAuthorization.setRoles(user1, roles);
notebookAuthorization.setRoles(user2, roles);
Note note = notebook.createNote(new AuthenticationInfo(user1));
// check that user1 is owner, reader and writer
assertEquals(notebookAuthorization.isOwner(note.getId(),
Sets.newHashSet(user1)), true);
assertEquals(notebookAuthorization.isReader(note.getId(),
Sets.newHashSet(user1)), true);
assertEquals(notebookAuthorization.isWriter(note.getId(),
Sets.newHashSet(user1)), true);
// since user1 and user2 both have admin role, user2 will be reader and writer as well
assertEquals(notebookAuthorization.isOwner(note.getId(),
Sets.newHashSet(user2)), false);
assertEquals(notebookAuthorization.isReader(note.getId(),
Sets.newHashSet(user2)), true);
assertEquals(notebookAuthorization.isWriter(note.getId(),
Sets.newHashSet(user2)), true);
// check that user1 has note listed in his workbench
Set<String> user1AndRoles = notebookAuthorization.getRoles(user1);
user1AndRoles.add(user1);
List<Note> user1Notes = notebook.getAllNotes(user1AndRoles);
assertEquals(user1Notes.size(), 1);
assertEquals(user1Notes.get(0).getId(), note.getId());
// check that user2 has note listed in his workbech because of admin role
Set<String> user2AndRoles = notebookAuthorization.getRoles(user2);
user2AndRoles.add(user2);
List<Note> user2Notes = notebook.getAllNotes(user2AndRoles);
assertEquals(user2Notes.size(), 1);
assertEquals(user2Notes.get(0).getId(), note.getId());
}
@Test
public void testAbortParagraphStatusOnInterpreterRestart() throws InterruptedException,
IOException {