mirror of
https://github.com/SpencerPark/IJava.git
synced 2025-04-19 21:06:08 +00:00
Compare commits
19 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a03ad7712a | ||
![]() |
554c9a0339 | ||
![]() |
3975e47f7f | ||
![]() |
d6695414d8 | ||
![]() |
3ea6536b82 | ||
![]() |
c594285afa | ||
![]() |
c99a809dc3 | ||
![]() |
a920ff3a27 | ||
![]() |
fe14b7313e | ||
![]() |
8e7b6b62b1 | ||
![]() |
4ceadf40df | ||
![]() |
8d030b040c | ||
![]() |
7e0da04cfe | ||
![]() |
ed1c8fe1df | ||
![]() |
b5945808c6 | ||
![]() |
3171f924d0 | ||
![]() |
ef44f8f900 | ||
![]() |
4d1ee69e39 | ||
![]() |
98386ad554 |
15
build.gradle
15
build.gradle
@ -2,7 +2,7 @@ plugins {
|
||||
id 'java'
|
||||
id 'maven-publish'
|
||||
id('com.github.hierynomus.license') version '0.14.0'
|
||||
id('io.github.spencerpark.jupyter-kernel-installer') version '2.0.0'
|
||||
id('io.github.spencerpark.jupyter-kernel-installer') version '2.1.0'
|
||||
id('com.github.jk1.dependency-license-report')
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import com.github.jk1.license.filter.*
|
||||
import io.github.spencerpark.gradle.*
|
||||
|
||||
group = 'io.github.spencerpark'
|
||||
version = '1.2.0'
|
||||
version = '1.3.0'
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '4.8.1'
|
||||
@ -68,13 +68,11 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
shade group: 'io.github.spencerpark', name: 'jupyter-jvm-basekernel', version: '2.2.3'
|
||||
shade group: 'io.github.spencerpark', name: 'jupyter-jvm-basekernel', version: '2.3.0'
|
||||
|
||||
shade group: 'org.jboss.shrinkwrap.resolver', name: 'shrinkwrap-resolver-impl-maven', version: '3.1.3'
|
||||
|
||||
// Transitive shrinkwrap but repeated to be explicit
|
||||
shade group: 'org.slf4j', name: 'slf4j-api', version: '1.7.22'
|
||||
shade group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.22'
|
||||
shade group: 'org.apache.ivy', name: 'ivy', version: '2.5.0-rc1'
|
||||
//shade group: 'org.apache.maven', name: 'maven-settings-builder', version: '3.6.0'
|
||||
shade group: 'org.apache.maven', name: 'maven-model-builder', version: '3.6.0'
|
||||
|
||||
testCompile group: 'junit', name: 'junit', version: '4.12'
|
||||
}
|
||||
@ -140,7 +138,6 @@ jupyter {
|
||||
}
|
||||
|
||||
installKernel {
|
||||
//pythonExecutable = 'python'
|
||||
kernelInstallPath = commandLineSpecifiedPath(userInstallPath)
|
||||
}
|
||||
|
||||
|
@ -4,21 +4,21 @@ One of the many great things about the Jupyter front ends is the support for [`d
|
||||
|
||||
## Notebook functions
|
||||
|
||||
IJava injects 2 functions into the user space for displaying data: `display` and `render`. Most use cases should prefer the former but there is a necessary case for `render` that is outline below. Both are defined in [ijava-display-init.jshell](/src/main/resources/ijava-display-init.jshell).
|
||||
IJava injects 2 functions into the user space for displaying data: `display` and `render`. Most use cases should prefer the former but there is a necessary case for `render` that is outline below. In addition the `updateDisplay` function can be used to update a previously displayed object. All are defined in the runtime [Display](/src/main/java/io/github/spencerpark/ijava/runtime/Display.java) class.
|
||||
|
||||
All display/render functions include a `text/plain` representation in their output. By default this is the `String.valueOf(Object)` value but it can be overridden.
|
||||
|
||||
### `display(Object o)`
|
||||
### `String display(Object o)`
|
||||
|
||||
Display an object as it's **preferred** types. If you don't want a specific type it is best to let the object decide how it is best represented.
|
||||
|
||||
The object is rendered and published on the display stream.
|
||||
The object is rendered and published on the display stream. An id is returned which can be used to `updateDisplay` if desired.
|
||||
|
||||
### `display(Object o, String... as)`
|
||||
### `String display(Object o, String... as)`
|
||||
|
||||
Display an object as the **requested** types. In this case the object attempts to be rendered as the desired mime types given in `as`. No promises though, if a type is unsupported it will simply not appear in the output.
|
||||
|
||||
The object is rendered and published on the display stream.
|
||||
The object is rendered and published on the display stream. An id is returned which can be used to `updateDisplay` if desired.
|
||||
|
||||
This is useful when a type has many potential representations but not all are preferred. For example a `CharSequence` has many representations but only the `text/plain` is preferred. To display it as executable javascript we can use the following:
|
||||
|
||||
@ -26,13 +26,20 @@ This is useful when a type has many potential representations but not all are pr
|
||||
display("alert('Hello from IJava!');", "application/javascript");
|
||||
```
|
||||
|
||||
Since there is the potential that some front ends don't support a given format many can be given and the front end chooses the best.
|
||||
Since there is the potential that some front ends don't support a given format many can be given and the front end chooses the best. For example, to display as html and markdown:
|
||||
|
||||
### `render(Object o)`
|
||||
```java
|
||||
display("<b>Bold</b>", "text/html", "text/markdown");
|
||||
```
|
||||
|
||||
This will trigger a display message with values for `text/html`, `text/markdown`, and the implicit `text/plain`.
|
||||
|
||||
|
||||
### `DisplayData render(Object o)`
|
||||
|
||||
Renders an object as it's **preferred** types and returns it's rendered format. Similar to `display(Object o)` but without publishing the result.
|
||||
|
||||
### `render(Object o, String... as)`
|
||||
### `DisplayData render(Object o, String... as)`
|
||||
|
||||
Renders an object as the **requested** types and returns it's rendered format. Similar to `display(Object o, String... as)` but without publishing the result.
|
||||
|
||||
@ -46,4 +53,19 @@ render(md, "text/markdown")
|
||||
|
||||
This will result in the `Out[_]` result to be the pretty `text/markdown` representation rather than the boring `text/plain` representation.
|
||||
|
||||
### `void updateDisplay(String id, Object o)`
|
||||
|
||||
Renders an object as it's **preferred** types and updates an existing display with the given id to contain the new rendered object. Similar to `display(Object o)` but updates an existing displayed object instead of appending a new one.
|
||||
|
||||
### `void updateDisplay(String id, Object o, String... as)`
|
||||
|
||||
Renders an object as it's **requested** types and updates an existing display with the given id to contain the new rendered object. Similar to `display(Object o, String... as)` but updates an existing displayed object instead of appending a new one.
|
||||
|
||||
```java
|
||||
String id = display("<b>Countdown:</b> 3", "text/html");
|
||||
for (int i = 3; i >= 0; i--) {
|
||||
updateDisplay(id, "<b>Countdown:</b> " + i, "text/html");
|
||||
Thread.sleep(1000L);
|
||||
}
|
||||
render("<b>Liftoff!</b>", "text/html")
|
||||
```
|
22
docs/kernel.md
Normal file
22
docs/kernel.md
Normal file
@ -0,0 +1,22 @@
|
||||
# Kernel
|
||||
|
||||
All code running in IJava flows through the kernel. This makes it the place to register magics, add things to the classpath, and perform many jupyter related operations.
|
||||
|
||||
## Notebook functions
|
||||
|
||||
IJava injects a function for getting the active kernel instance and additional helpers for making use of the kernel at runtime. These are defined in the runtime [Kernel](/src/main/java/io/github/spencerpark/ijava/runtime/Kernel.java) class.
|
||||
|
||||
### `JavaKernel getKernelInstance()`
|
||||
|
||||
Get a reference to the current kernel. It may return null if called outside of a kernel context but should be considered `@NonNull` when inside a notebook or similar. The kernel api has lots of goodies, look at the [JavaKernel](/src/main/java/io/github/spencerpark/ijava/runtime/Kernel.java) class for more information. Specifically there is access to adding to the classpath, getting the magics registry and maven resolver, and access to eval.
|
||||
|
||||
### `Object eval(String expr) throws Exception`
|
||||
|
||||
The `eval` function provides full access to the code evaluation mechanism of the kernel. It evaluates the code in the _same_ scope as the kernel and **returns an object**. This object is an object that lives in the kernel!
|
||||
|
||||
The given expression can be anything you would write in a cell, including magics.
|
||||
|
||||
```java
|
||||
(int) eval("1 + 2") + 3
|
||||
```
|
||||
|
@ -44,7 +44,18 @@ Add jars to the notebook classpath.
|
||||
###### Line magic
|
||||
|
||||
* **arguments**:
|
||||
* _varargs_ list of simple glob paths to jars on the local file system
|
||||
* _varargs_ list of simple glob paths to jars on the local file system. If a glob matches a directory all files in that directory will be added.
|
||||
|
||||
|
||||
|
||||
### classpath
|
||||
|
||||
Add entries to the notebook classpath.
|
||||
|
||||
###### Line magic
|
||||
|
||||
* **arguments**:
|
||||
* _varargs_ list of simple glob paths to entries on the local file system. This includes directories or jars.
|
||||
|
||||
|
||||
|
||||
|
@ -46,9 +46,6 @@ public class IJava {
|
||||
public static final String STARTUP_SCRIPT_KEY = "IJAVA_STARTUP_SCRIPT";
|
||||
|
||||
public static final String DEFAULT_SHELL_INIT_RESOURCE_PATH = "ijava-jshell-init.jshell";
|
||||
public static final String MAGICS_INIT_RESOURCE_PATH = "ijava-magics-init.jshell";
|
||||
public static final String DISPLAY_INIT_RESOURCE_PATH = "ijava-display-init.jshell";
|
||||
public static final String EVAL_INIT_RESOURCE_PATH = "ijava-eval-init.jshell";
|
||||
|
||||
public static final String VERSION;
|
||||
|
||||
|
@ -24,24 +24,24 @@
|
||||
package io.github.spencerpark.ijava;
|
||||
|
||||
import io.github.spencerpark.ijava.execution.*;
|
||||
import io.github.spencerpark.ijava.magics.ClasspathMagics;
|
||||
import io.github.spencerpark.ijava.magics.MavenResolver;
|
||||
import io.github.spencerpark.jupyter.kernel.BaseKernel;
|
||||
import io.github.spencerpark.jupyter.kernel.LanguageInfo;
|
||||
import io.github.spencerpark.jupyter.kernel.ReplacementOptions;
|
||||
import io.github.spencerpark.jupyter.kernel.display.DisplayData;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.Magics;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.common.Load;
|
||||
import io.github.spencerpark.jupyter.kernel.util.CharPredicate;
|
||||
import io.github.spencerpark.jupyter.kernel.util.GlobFinder;
|
||||
import io.github.spencerpark.jupyter.kernel.util.StringStyler;
|
||||
import io.github.spencerpark.jupyter.kernel.util.TextColor;
|
||||
import io.github.spencerpark.jupyter.messages.Header;
|
||||
import jdk.jshell.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class JavaKernel extends BaseKernel {
|
||||
public static String completeCodeSignifier() {
|
||||
@ -81,9 +81,6 @@ public class JavaKernel extends BaseKernel {
|
||||
.addClasspathFromString(System.getenv(IJava.CLASSPATH_KEY))
|
||||
.compilerOptsFromString(System.getenv(IJava.COMPILER_OPTS_KEY))
|
||||
.startupScript(IJava.resource(IJava.DEFAULT_SHELL_INIT_RESOURCE_PATH))
|
||||
.startupScript(IJava.resource(IJava.MAGICS_INIT_RESOURCE_PATH))
|
||||
.startupScript(IJava.resource(IJava.DISPLAY_INIT_RESOURCE_PATH))
|
||||
.startupScript(IJava.resource(IJava.EVAL_INIT_RESOURCE_PATH))
|
||||
.startupScriptFiles(System.getenv(IJava.STARTUP_SCRIPTS_KEY))
|
||||
.startupScript(System.getenv(IJava.STARTUP_SCRIPT_KEY))
|
||||
.timeoutFromString(System.getenv(IJava.TIMEOUT_DURATION_KEY))
|
||||
@ -96,26 +93,13 @@ public class JavaKernel extends BaseKernel {
|
||||
this.magicsTransformer = new MagicsSourceTransformer();
|
||||
this.magics = new Magics();
|
||||
this.magics.registerMagics(this.mavenResolver);
|
||||
this.magics.registerLineMagic("jars", args -> {
|
||||
List<String> jars = args.stream()
|
||||
.map(GlobFinder::new)
|
||||
.flatMap(g -> {
|
||||
try {
|
||||
return StreamSupport.stream(g.computeMatchingPaths().spliterator(), false);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Exception resolving jar glob", e);
|
||||
}
|
||||
})
|
||||
.map(p -> p.toAbsolutePath().toString())
|
||||
.collect(Collectors.toList());
|
||||
jars.forEach(this::addToClasspath);
|
||||
return jars;
|
||||
});
|
||||
this.magics.registerMagics(new ClasspathMagics(this::addToClasspath));
|
||||
this.magics.registerMagics(new Load(List.of(".jsh", ".jshell", ".java", ".ijava"), this::eval));
|
||||
|
||||
this.languageInfo = new LanguageInfo.Builder("Java")
|
||||
.version(Runtime.version().toString())
|
||||
.mimetype("text/x-java-source")
|
||||
.fileExtension(".java")
|
||||
.fileExtension(".jshell")
|
||||
.pygments("java")
|
||||
.codemirror("java")
|
||||
.build();
|
||||
@ -367,7 +351,7 @@ public class JavaKernel extends BaseKernel {
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new ReplacementOptions(options, replaceStart[0], at + 1);
|
||||
return new ReplacementOptions(options, replaceStart[0], at);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,270 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Spencer Park
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package io.github.spencerpark.ijava;
|
||||
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.CellMagic;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.LineMagic;
|
||||
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.ConfigurableMavenResolverSystem;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.Maven;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.PomEquippedResolveStage;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.ScopeType;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.repository.MavenRemoteRepositories;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.repository.MavenRemoteRepository;
|
||||
import org.jboss.shrinkwrap.resolver.api.maven.strategy.TransitiveStrategy;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MavenResolver {
|
||||
private final Consumer<String> addToClasspath;
|
||||
private final List<MavenRemoteRepository> repos;
|
||||
|
||||
public MavenResolver(Consumer<String> addToClasspath) {
|
||||
this.addToClasspath = addToClasspath;
|
||||
this.repos = new LinkedList<>();
|
||||
}
|
||||
|
||||
public void addRemoteRepo(String name, String url) {
|
||||
this.repos.add(MavenRemoteRepositories.createRemoteRepository(name, url, "default"));
|
||||
}
|
||||
|
||||
public void addRemoteRepo(String name, URL url) {
|
||||
this.repos.add(MavenRemoteRepositories.createRemoteRepository(name, url, "default"));
|
||||
}
|
||||
|
||||
public List<File> resolveMavenDependency(String canonical) {
|
||||
ConfigurableMavenResolverSystem resolver = Maven.configureResolver()
|
||||
.withClassPathResolution(true)
|
||||
.withMavenCentralRepo(true);
|
||||
|
||||
this.repos.forEach(resolver::withRemoteRepo);
|
||||
|
||||
return resolver.resolve(canonical)
|
||||
.using(TransitiveStrategy.INSTANCE)
|
||||
.asList(File.class);
|
||||
}
|
||||
|
||||
private String solidifyPartialPOM(String rawIn) throws ParserConfigurationException, IOException, SAXException, TransformerException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
// Wrap in a dummy tag to allow fragments
|
||||
InputStream inStream = new SequenceInputStream(Collections.enumeration(Arrays.asList(
|
||||
new ByteArrayInputStream("<ijava>".getBytes(Charset.forName("utf-8"))),
|
||||
new ByteArrayInputStream(rawIn.getBytes(Charset.forName("utf-8"))),
|
||||
new ByteArrayInputStream("</ijava>".getBytes(Charset.forName("utf-8")))
|
||||
)));
|
||||
|
||||
Document doc = builder.parse(inStream);
|
||||
NodeList rootChildren = doc.getDocumentElement().getChildNodes();
|
||||
|
||||
// If input was a single "project" tag then we don't touch it. It is assumed
|
||||
// to be complete.
|
||||
if (rootChildren.getLength() == 1 && "project".equalsIgnoreCase(rootChildren.item(0).getNodeName()))
|
||||
return this.writeDOM(new DOMSource(rootChildren.item(0)));
|
||||
|
||||
// Put the pieces together and fill in the blanks.
|
||||
Document fixed = builder.newDocument();
|
||||
|
||||
Node project = fixed.appendChild(fixed.createElement("project"));
|
||||
|
||||
Node dependencies = project.appendChild(fixed.createElement("dependencies"));
|
||||
Node repositories = project.appendChild(fixed.createElement("repositories"));
|
||||
|
||||
boolean setModelVersion = false;
|
||||
boolean setGroupId = false;
|
||||
boolean setArtifactId = false;
|
||||
boolean setVersion = false;
|
||||
|
||||
for (int i = 0; i < rootChildren.getLength(); i++) {
|
||||
Node child = rootChildren.item(i);
|
||||
|
||||
switch (child.getNodeName()) {
|
||||
case "modelVersion":
|
||||
setModelVersion = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "groupId":
|
||||
setGroupId = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "artifactId":
|
||||
setArtifactId = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "version":
|
||||
setVersion = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "dependency":
|
||||
this.appendChildInNewDoc(child, fixed, dependencies);
|
||||
break;
|
||||
case "repository":
|
||||
this.appendChildInNewDoc(child, fixed, repositories);
|
||||
break;
|
||||
case "dependencies":
|
||||
// Add all dependencies to the collecting tag
|
||||
NodeList dependencyChildren = child.getChildNodes();
|
||||
for (int j = 0; j < dependencyChildren.getLength(); j++)
|
||||
this.appendChildInNewDoc(dependencyChildren.item(j), fixed, dependencies);
|
||||
break;
|
||||
case "repositories":
|
||||
// Add all repositories to the collecting tag
|
||||
NodeList repositoryChildren = child.getChildNodes();
|
||||
for (int j = 0; j < repositoryChildren.getLength(); j++)
|
||||
this.appendChildInNewDoc(repositoryChildren.item(j), fixed, repositories);
|
||||
break;
|
||||
default:
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!setModelVersion) {
|
||||
Node modelVersion = project.appendChild(fixed.createElement("modelVersion"));
|
||||
modelVersion.setTextContent("4.0.0");
|
||||
}
|
||||
|
||||
if (!setGroupId) {
|
||||
Node groupId = project.appendChild(fixed.createElement("groupId"));
|
||||
groupId.setTextContent("ijava.notebook");
|
||||
}
|
||||
|
||||
if (!setArtifactId) {
|
||||
Node artifactId = project.appendChild(fixed.createElement("artifactId"));
|
||||
artifactId.setTextContent("cell");
|
||||
}
|
||||
|
||||
if (!setVersion) {
|
||||
Node version = project.appendChild(fixed.createElement("version"));
|
||||
version.setTextContent("1");
|
||||
}
|
||||
|
||||
return this.writeDOM(new DOMSource(fixed));
|
||||
}
|
||||
|
||||
private void appendChildInNewDoc(Node oldNode, Document doc, Node newParent) {
|
||||
Node newNode = oldNode.cloneNode(true);
|
||||
doc.adoptNode(newNode);
|
||||
newParent.appendChild(newNode);
|
||||
}
|
||||
|
||||
private String writeDOM(Source src) throws TransformerException, UnsupportedEncodingException {
|
||||
Transformer idTransformer = TransformerFactory.newInstance().newTransformer();
|
||||
idTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Result dest = new StreamResult(out);
|
||||
|
||||
idTransformer.transform(src, dest);
|
||||
|
||||
return out.toString("utf-8");
|
||||
}
|
||||
|
||||
public void addJarsToClasspath(Iterable<String> jars) {
|
||||
jars.forEach(this.addToClasspath);
|
||||
}
|
||||
|
||||
@LineMagic(aliases = { "addMavenDependency", "maven" })
|
||||
public void addMavenDependencies(List<String> args) {
|
||||
for (String arg : args) {
|
||||
this.addJarsToClasspath(
|
||||
this.resolveMavenDependency(arg).stream()
|
||||
.map(File::getAbsolutePath)
|
||||
::iterator
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@LineMagic(aliases = { "mavenRepo" })
|
||||
public void addMavenRepo(List<String> args) {
|
||||
if (args.size() != 2)
|
||||
throw new IllegalArgumentException("Expected 2 arguments: repository id and url. Got: " + args);
|
||||
|
||||
String id = args.get(0);
|
||||
String url = args.get(1);
|
||||
|
||||
this.addRemoteRepo(id, url);
|
||||
}
|
||||
|
||||
@CellMagic
|
||||
public void loadFromPOM(List<String> args, String body) throws Exception {
|
||||
try {
|
||||
Path tempPom = Files.createTempFile("ijava-maven-", ".pom");
|
||||
String rawPom = this.solidifyPartialPOM(body);
|
||||
Files.write(tempPom, rawPom.getBytes(Charset.forName("utf-8")));
|
||||
|
||||
List<String> loadArgs = new ArrayList<>(args.size() + 1);
|
||||
loadArgs.add(tempPom.toAbsolutePath().toString());
|
||||
loadArgs.addAll(args);
|
||||
|
||||
this.loadFromPOM(loadArgs);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@LineMagic
|
||||
public void loadFromPOM(List<String> args) {
|
||||
if (args.isEmpty())
|
||||
throw new IllegalArgumentException("Loading from POM requires at least the path to the POM file");
|
||||
|
||||
String pomFile = args.get(0);
|
||||
List<String> scopes = args.subList(1, args.size());
|
||||
|
||||
PomEquippedResolveStage stage = Maven.resolver().loadPomFromFile(pomFile);
|
||||
|
||||
if (scopes.isEmpty())
|
||||
stage = stage.importCompileAndRuntimeDependencies();
|
||||
else
|
||||
stage = stage.importDependencies(scopes.stream().map(ScopeType::fromScopeType).toArray(ScopeType[]::new));
|
||||
|
||||
this.addJarsToClasspath(
|
||||
stage.resolve()
|
||||
.withTransitivity()
|
||||
.asList(File.class).stream()
|
||||
.map(File::getAbsolutePath)
|
||||
::iterator
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package io.github.spencerpark.ijava.magics;
|
||||
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.LineMagic;
|
||||
import io.github.spencerpark.jupyter.kernel.util.GlobFinder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class ClasspathMagics {
|
||||
private final Consumer<String> addToClasspath;
|
||||
|
||||
public ClasspathMagics(Consumer<String> addToClasspath) {
|
||||
this.addToClasspath = addToClasspath;
|
||||
}
|
||||
|
||||
@LineMagic
|
||||
public List<String> jars(List<String> args) {
|
||||
List<String> jars = args.stream()
|
||||
.map(GlobFinder::new)
|
||||
.flatMap(g -> {
|
||||
try {
|
||||
return StreamSupport.stream(g.computeMatchingFiles().spliterator(), false);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Exception resolving jar glob", e);
|
||||
}
|
||||
})
|
||||
.map(p -> p.toAbsolutePath().toString())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
jars.forEach(this.addToClasspath);
|
||||
|
||||
return jars;
|
||||
}
|
||||
|
||||
@LineMagic
|
||||
public List<String> classpath(List<String> args) {
|
||||
List<String> paths = args.stream()
|
||||
.map(GlobFinder::new)
|
||||
.flatMap(g -> {
|
||||
try {
|
||||
return StreamSupport.stream(g.computeMatchingPaths().spliterator(), false);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Exception resolving jar glob", e);
|
||||
}
|
||||
})
|
||||
.map(p -> p.toAbsolutePath().toString())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
paths.forEach(this.addToClasspath);
|
||||
|
||||
return paths;
|
||||
}
|
||||
}
|
@ -0,0 +1,524 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Spencer Park
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package io.github.spencerpark.ijava.magics;
|
||||
|
||||
import io.github.spencerpark.ijava.magics.dependencies.CommonRepositories;
|
||||
import io.github.spencerpark.ijava.magics.dependencies.Maven;
|
||||
import io.github.spencerpark.ijava.magics.dependencies.MavenToIvy;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.CellMagic;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.LineMagic;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.MagicsArgs;
|
||||
import org.apache.ivy.Ivy;
|
||||
import org.apache.ivy.core.module.descriptor.DefaultModuleDescriptor;
|
||||
import org.apache.ivy.core.module.descriptor.ModuleDescriptor;
|
||||
import org.apache.ivy.core.module.id.ModuleRevisionId;
|
||||
import org.apache.ivy.core.report.ArtifactDownloadReport;
|
||||
import org.apache.ivy.core.report.ResolveReport;
|
||||
import org.apache.ivy.core.resolve.ResolveOptions;
|
||||
import org.apache.ivy.core.settings.IvySettings;
|
||||
import org.apache.ivy.plugins.parser.m2.PomModuleDescriptorParser;
|
||||
import org.apache.ivy.plugins.repository.url.URLResource;
|
||||
import org.apache.ivy.plugins.resolver.ChainResolver;
|
||||
import org.apache.ivy.plugins.resolver.DependencyResolver;
|
||||
import org.apache.ivy.util.DefaultMessageLogger;
|
||||
import org.apache.ivy.util.Message;
|
||||
import org.apache.ivy.util.MessageLogger;
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.building.ModelBuildingException;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.text.ParseException;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MavenResolver {
|
||||
private static final String DEFAULT_RESOLVER_NAME = "default";
|
||||
|
||||
/**
|
||||
* "master" includes the artifact published by the module.
|
||||
* "runtime" includes the dependencies required for the module to run and
|
||||
* extends "compile" which is the dependencies required to compile the module.
|
||||
*/
|
||||
private static final String[] DEFAULT_RESOLVE_CONFS = { "master", "runtime" };
|
||||
|
||||
/**
|
||||
* The ivy artifact type corresponding to a binary artifact for a module.
|
||||
*/
|
||||
private static final String JAR_TYPE = "jar";
|
||||
|
||||
/**
|
||||
* The ivy artifact type corresponding to a source code artifact for a module. This
|
||||
* is still usually a ".jar" file but that corresponds to the "ext" not the "type".
|
||||
*/
|
||||
private static final String SOURCE_TYPE = "source";
|
||||
|
||||
/**
|
||||
* The ivy artifact type corresponding to a javadoc (HTML) artifact for a module. This
|
||||
* is still usually a ".jar" file but that corresponds to the "ext" not the "type".
|
||||
*/
|
||||
private static final String JAVADOC_TYPE = "javadoc";
|
||||
|
||||
private static final Pattern IVY_MRID_PATTERN = Pattern.compile(
|
||||
"^(?<organization>[-\\w/._+=]*)#(?<name>[-\\w/._+=]+)(?:#(?<branch>[-\\w/._+=]+))?;(?<revision>[-\\w/._+=,\\[\\]{}():@]+)$"
|
||||
);
|
||||
private static final Pattern MAVEN_MRID_PATTERN = Pattern.compile(
|
||||
"^(?<group>[^:\\s]+):(?<artifact>[^:\\s]+)(?::(?<packaging>[^:\\s]*)(?::(?<classifier>[^:\\s]+))?)?:(?<version>[^:\\s]+)$"
|
||||
);
|
||||
|
||||
private final Consumer<String> addToClasspath;
|
||||
private final List<DependencyResolver> repos;
|
||||
|
||||
public MavenResolver(Consumer<String> addToClasspath) {
|
||||
this.addToClasspath = addToClasspath;
|
||||
this.repos = new LinkedList<>();
|
||||
this.repos.add(CommonRepositories.mavenCentral());
|
||||
this.repos.add(CommonRepositories.mavenLocal());
|
||||
}
|
||||
|
||||
public void addRemoteRepo(String name, String url) {
|
||||
if (DEFAULT_RESOLVER_NAME.equals(name))
|
||||
throw new IllegalArgumentException("Illegal repository name, cannot use '" + DEFAULT_RESOLVER_NAME + "'.");
|
||||
|
||||
this.repos.add(CommonRepositories.maven(name, url));
|
||||
}
|
||||
|
||||
private ChainResolver searchAllReposResolver(Set<String> repos) {
|
||||
ChainResolver resolver = new ChainResolver();
|
||||
resolver.setName(DEFAULT_RESOLVER_NAME);
|
||||
|
||||
this.repos.stream()
|
||||
.filter(r -> repos == null || repos.contains(r.getName().toLowerCase()))
|
||||
.forEach(resolver::add);
|
||||
|
||||
if (repos != null) {
|
||||
Set<String> resolverNames = resolver.getResolvers().stream()
|
||||
.map(d -> d.getName().toLowerCase())
|
||||
.collect(Collectors.toSet());
|
||||
repos.removeAll(resolverNames);
|
||||
|
||||
repos.forEach(r -> {
|
||||
try {
|
||||
URL url = new URL(r);
|
||||
resolver.add(CommonRepositories.maven("from-" + url.getHost(), r));
|
||||
} catch (MalformedURLException e) {
|
||||
// Ignore as we will assume that a bad url was a name
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return resolver;
|
||||
}
|
||||
|
||||
private static ModuleRevisionId parseCanonicalArtifactName(String canonical) {
|
||||
Matcher m = IVY_MRID_PATTERN.matcher(canonical);
|
||||
if (m.matches()) {
|
||||
return ModuleRevisionId.newInstance(
|
||||
m.group("organization"),
|
||||
m.group("name"),
|
||||
m.group("branch"),
|
||||
m.group("revision")
|
||||
);
|
||||
}
|
||||
|
||||
m = MAVEN_MRID_PATTERN.matcher(canonical);
|
||||
if (m.matches()) {
|
||||
String packaging = m.group("packaging");
|
||||
String classifier = m.group("classifier");
|
||||
|
||||
return ModuleRevisionId.newInstance(
|
||||
m.group("group"),
|
||||
m.group("artifact"),
|
||||
m.group("version"),
|
||||
packaging == null
|
||||
? Collections.emptyMap()
|
||||
: classifier == null
|
||||
? Map.of("ext", packaging)
|
||||
: Map.of("ext", packaging, "m:classifier", classifier)
|
||||
);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Cannot resolve '" + canonical + "' as maven or ivy coordinates.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an ivy instance with the specified verbosity. The instance is relatively plain.
|
||||
*
|
||||
* @param verbosity the verbosity level.
|
||||
* <ol start="0">
|
||||
* <li>ERROR</li>
|
||||
* <li>WANRING</li>
|
||||
* <li>INFO</li>
|
||||
* <li>VERBOSE</li>
|
||||
* <li>DEBUG</li>
|
||||
* </ol>
|
||||
*
|
||||
* @return the fresh ivy instance.
|
||||
*/
|
||||
private Ivy createDefaultIvyInstance(int verbosity) {
|
||||
MessageLogger logger = new DefaultMessageLogger(verbosity);
|
||||
|
||||
// Set the default logger since not all things log to the ivy instance.
|
||||
Message.setDefaultLogger(logger);
|
||||
Ivy ivy = new Ivy();
|
||||
|
||||
ivy.getLoggerEngine().setDefaultLogger(logger);
|
||||
ivy.setSettings(new IvySettings());
|
||||
ivy.bind();
|
||||
|
||||
return ivy;
|
||||
}
|
||||
|
||||
// TODO support multiple at once. This is necessary for conflict resolution with multiple overlapping dependencies.
|
||||
// TODO support classpath resolution
|
||||
public List<File> resolveMavenDependency(String canonical, Set<String> repos, int verbosity) throws IOException, ParseException {
|
||||
ChainResolver rootResolver = this.searchAllReposResolver(repos);
|
||||
|
||||
Ivy ivy = this.createDefaultIvyInstance(verbosity);
|
||||
IvySettings settings = ivy.getSettings();
|
||||
|
||||
settings.addResolver(rootResolver);
|
||||
rootResolver.setCheckmodified(true);
|
||||
settings.setDefaultResolver(rootResolver.getName());
|
||||
|
||||
ivy.getLoggerEngine().info("Searching for dependencies in: " + rootResolver.getResolvers());
|
||||
|
||||
ResolveOptions resolveOptions = new ResolveOptions();
|
||||
resolveOptions.setTransitive(true);
|
||||
resolveOptions.setDownload(true);
|
||||
|
||||
ModuleRevisionId artifactIdentifier = MavenResolver.parseCanonicalArtifactName(canonical);
|
||||
DefaultModuleDescriptor containerModule = DefaultModuleDescriptor.newCallerInstance(
|
||||
artifactIdentifier,
|
||||
DEFAULT_RESOLVE_CONFS,
|
||||
true, // Transitive
|
||||
repos != null // Changing - the resolver will set this based on SNAPSHOT since they are all m2 compatible
|
||||
// but if `repos` is specified, we want to force a lookup.
|
||||
);
|
||||
|
||||
ResolveReport resolved = ivy.resolve(containerModule, resolveOptions);
|
||||
if (resolved.hasError()) {
|
||||
MessageLogger logger = ivy.getLoggerEngine();
|
||||
Arrays.stream(resolved.getAllArtifactsReports())
|
||||
.forEach(r -> {
|
||||
logger.error("download " + r.getDownloadStatus() + ": " + r.getArtifact() + " of " + r.getType());
|
||||
if (r.getArtifactOrigin() == null)
|
||||
logger.error("\tCouldn't find artifact.");
|
||||
else
|
||||
logger.error("\tfrom: " + r.getArtifactOrigin());
|
||||
});
|
||||
|
||||
// TODO better error...
|
||||
throw new RuntimeException("Error resolving '" + canonical + "'. " + resolved.getAllProblemMessages());
|
||||
}
|
||||
|
||||
return Arrays.stream(resolved.getAllArtifactsReports())
|
||||
.filter(a -> JAR_TYPE.equalsIgnoreCase(a.getType()))
|
||||
.map(ArtifactDownloadReport::getLocalFile)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private File convertPomToIvy(Ivy ivy, File pomFile) throws IOException, ParseException {
|
||||
PomModuleDescriptorParser parser = PomModuleDescriptorParser.getInstance();
|
||||
|
||||
URL pomUrl = pomFile.toURI().toURL();
|
||||
|
||||
ModuleDescriptor pomModule = parser.parseDescriptor(new IvySettings(), pomFile.toURI().toURL(), false);
|
||||
|
||||
File tempIvyFile = File.createTempFile("ijava-ivy-", ".xml").getAbsoluteFile();
|
||||
tempIvyFile.deleteOnExit();
|
||||
|
||||
parser.toIvyFile(pomUrl.openStream(), new URLResource(pomUrl), tempIvyFile, pomModule);
|
||||
|
||||
MessageLogger logger = ivy.getLoggerEngine();
|
||||
logger.info(new String(Files.readAllBytes(tempIvyFile.toPath()), Charset.forName("utf8")));
|
||||
|
||||
return tempIvyFile;
|
||||
}
|
||||
|
||||
private void addPomReposToIvySettings(IvySettings settings, File pomFile) throws ModelBuildingException {
|
||||
Model mavenModel = Maven.getInstance().readEffectiveModel(pomFile).getEffectiveModel();
|
||||
ChainResolver pomRepos = MavenToIvy.createChainForModelRepositories(mavenModel);
|
||||
pomRepos.setName(DEFAULT_RESOLVER_NAME);
|
||||
|
||||
settings.addResolver(pomRepos);
|
||||
settings.setDefaultResolver(DEFAULT_RESOLVER_NAME);
|
||||
}
|
||||
|
||||
private List<File> resolveFromIvyFile(Ivy ivy, File ivyFile, List<String> scopes) throws IOException, ParseException {
|
||||
ResolveOptions resolveOptions = new ResolveOptions();
|
||||
resolveOptions.setTransitive(true);
|
||||
resolveOptions.setDownload(true);
|
||||
resolveOptions.setConfs(!scopes.isEmpty()
|
||||
? scopes.toArray(new String[0])
|
||||
: DEFAULT_RESOLVE_CONFS
|
||||
);
|
||||
|
||||
ResolveReport resolved = ivy.resolve(ivyFile, resolveOptions);
|
||||
if (resolved.hasError())
|
||||
// TODO better error...
|
||||
throw new RuntimeException("Error resolving '" + ivyFile + "'. " + resolved.getAllProblemMessages());
|
||||
|
||||
return Arrays.stream(resolved.getAllArtifactsReports())
|
||||
.map(ArtifactDownloadReport::getLocalFile)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
private String solidifyPartialPOM(String rawIn) throws ParserConfigurationException, IOException, SAXException, TransformerException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
|
||||
// Wrap in a dummy tag to allow fragments
|
||||
InputStream inStream = new SequenceInputStream(Collections.enumeration(Arrays.asList(
|
||||
new ByteArrayInputStream("<ijava>".getBytes(Charset.forName("utf-8"))),
|
||||
new ByteArrayInputStream(rawIn.getBytes(Charset.forName("utf-8"))),
|
||||
new ByteArrayInputStream("</ijava>".getBytes(Charset.forName("utf-8")))
|
||||
)));
|
||||
|
||||
Document doc = builder.parse(inStream);
|
||||
NodeList rootChildren = doc.getDocumentElement().getChildNodes();
|
||||
|
||||
// If input was a single "project" tag then we don't touch it. It is assumed
|
||||
// to be complete.
|
||||
if (rootChildren.getLength() == 1 && "project".equalsIgnoreCase(rootChildren.item(0).getNodeName()))
|
||||
return this.writeDOM(new DOMSource(rootChildren.item(0)));
|
||||
|
||||
// Put the pieces together and fill in the blanks.
|
||||
Document fixed = builder.newDocument();
|
||||
|
||||
Node project = fixed.appendChild(fixed.createElement("project"));
|
||||
|
||||
Node dependencies = project.appendChild(fixed.createElement("dependencies"));
|
||||
Node repositories = project.appendChild(fixed.createElement("repositories"));
|
||||
|
||||
boolean setModelVersion = false;
|
||||
boolean setGroupId = false;
|
||||
boolean setArtifactId = false;
|
||||
boolean setVersion = false;
|
||||
|
||||
for (int i = 0; i < rootChildren.getLength(); i++) {
|
||||
Node child = rootChildren.item(i);
|
||||
|
||||
switch (child.getNodeName()) {
|
||||
case "modelVersion":
|
||||
setModelVersion = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "groupId":
|
||||
setGroupId = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "artifactId":
|
||||
setArtifactId = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "version":
|
||||
setVersion = true;
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
case "dependency":
|
||||
this.appendChildInNewDoc(child, fixed, dependencies);
|
||||
break;
|
||||
case "repository":
|
||||
this.appendChildInNewDoc(child, fixed, repositories);
|
||||
break;
|
||||
case "dependencies":
|
||||
// Add all dependencies to the collecting tag
|
||||
NodeList dependencyChildren = child.getChildNodes();
|
||||
for (int j = 0; j < dependencyChildren.getLength(); j++)
|
||||
this.appendChildInNewDoc(dependencyChildren.item(j), fixed, dependencies);
|
||||
break;
|
||||
case "repositories":
|
||||
// Add all repositories to the collecting tag
|
||||
NodeList repositoryChildren = child.getChildNodes();
|
||||
for (int j = 0; j < repositoryChildren.getLength(); j++)
|
||||
this.appendChildInNewDoc(repositoryChildren.item(j), fixed, repositories);
|
||||
break;
|
||||
default:
|
||||
this.appendChildInNewDoc(child, fixed, project);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!setModelVersion) {
|
||||
Node modelVersion = project.appendChild(fixed.createElement("modelVersion"));
|
||||
modelVersion.setTextContent("4.0.0");
|
||||
}
|
||||
|
||||
if (!setGroupId) {
|
||||
Node groupId = project.appendChild(fixed.createElement("groupId"));
|
||||
groupId.setTextContent("ijava.notebook");
|
||||
}
|
||||
|
||||
if (!setArtifactId) {
|
||||
Node artifactId = project.appendChild(fixed.createElement("artifactId"));
|
||||
artifactId.setTextContent("cell");
|
||||
}
|
||||
|
||||
if (!setVersion) {
|
||||
Node version = project.appendChild(fixed.createElement("version"));
|
||||
version.setTextContent("1");
|
||||
}
|
||||
|
||||
return this.writeDOM(new DOMSource(fixed));
|
||||
}
|
||||
|
||||
private void appendChildInNewDoc(Node oldNode, Document doc, Node newParent) {
|
||||
Node newNode = oldNode.cloneNode(true);
|
||||
doc.adoptNode(newNode);
|
||||
newParent.appendChild(newNode);
|
||||
}
|
||||
|
||||
private String writeDOM(Source src) throws TransformerException, UnsupportedEncodingException {
|
||||
Transformer idTransformer = TransformerFactory.newInstance().newTransformer();
|
||||
idTransformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Result dest = new StreamResult(out);
|
||||
|
||||
idTransformer.transform(src, dest);
|
||||
|
||||
return out.toString("utf-8");
|
||||
}
|
||||
|
||||
public void addJarsToClasspath(Iterable<String> jars) {
|
||||
jars.forEach(this.addToClasspath);
|
||||
}
|
||||
|
||||
@LineMagic(aliases = { "addMavenDependency", "maven" })
|
||||
public void addMavenDependencies(List<String> args) {
|
||||
MagicsArgs schema = MagicsArgs.builder()
|
||||
.varargs("deps")
|
||||
.keyword("from")
|
||||
.flag("verbose", 'v')
|
||||
.onlyKnownKeywords()
|
||||
.onlyKnownFlags()
|
||||
.build();
|
||||
|
||||
Map<String, List<String>> vals = schema.parse(args);
|
||||
|
||||
List<String> deps = vals.get("deps");
|
||||
List<String> from = vals.get("from");
|
||||
int verbosity = vals.get("verbose").size();
|
||||
|
||||
Set<String> repos = from.isEmpty() ? null : new LinkedHashSet<>(from);
|
||||
|
||||
|
||||
for (String dep : deps) {
|
||||
try {
|
||||
this.addJarsToClasspath(
|
||||
this.resolveMavenDependency(dep, repos, verbosity).stream()
|
||||
.map(File::getAbsolutePath)
|
||||
::iterator
|
||||
);
|
||||
} catch (IOException | ParseException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@LineMagic(aliases = { "mavenRepo" })
|
||||
public void addMavenRepo(List<String> args) {
|
||||
MagicsArgs schema = MagicsArgs.builder().required("id").required("url").build();
|
||||
Map<String, List<String>> vals = schema.parse(args);
|
||||
|
||||
String id = vals.get("id").get(0);
|
||||
String url = vals.get("url").get(0);
|
||||
|
||||
this.addRemoteRepo(id, url);
|
||||
}
|
||||
|
||||
@CellMagic
|
||||
public void loadFromPOM(List<String> args, String body) throws Exception {
|
||||
try {
|
||||
File tempPomPath = File.createTempFile("ijava-maven-", ".pom").getAbsoluteFile();
|
||||
tempPomPath.deleteOnExit();
|
||||
|
||||
String rawPom = this.solidifyPartialPOM(body);
|
||||
Files.write(tempPomPath.toPath(), rawPom.getBytes(Charset.forName("utf-8")));
|
||||
|
||||
List<String> loadArgs = new ArrayList<>(args.size() + 1);
|
||||
loadArgs.add(tempPomPath.getAbsolutePath());
|
||||
loadArgs.addAll(args);
|
||||
|
||||
this.loadFromPOM(loadArgs);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@LineMagic
|
||||
public void loadFromPOM(List<String> args) {
|
||||
if (args.isEmpty())
|
||||
throw new IllegalArgumentException("Loading from POM requires at least the path to the POM file");
|
||||
|
||||
MagicsArgs schema = MagicsArgs.builder()
|
||||
.required("pomPath")
|
||||
.varargs("scopes")
|
||||
.flag("verbose", 'v')
|
||||
.onlyKnownKeywords().onlyKnownFlags().build();
|
||||
|
||||
Map<String, List<String>> vals = schema.parse(args);
|
||||
|
||||
String pomPath = vals.get("pomPath").get(0);
|
||||
List<String> scopes = vals.get("scopes");
|
||||
int verbosity = vals.get("verbose").size();
|
||||
|
||||
File pomFile = new File(pomPath);
|
||||
try {
|
||||
Ivy ivy = this.createDefaultIvyInstance(verbosity);
|
||||
IvySettings settings = ivy.getSettings();
|
||||
|
||||
File ivyFile = this.convertPomToIvy(ivy, pomFile);
|
||||
|
||||
this.addPomReposToIvySettings(settings, pomFile);
|
||||
|
||||
this.addJarsToClasspath(
|
||||
this.resolveFromIvyFile(ivy, ivyFile, scopes).stream()
|
||||
.map(File::getAbsolutePath)
|
||||
::iterator
|
||||
);
|
||||
} catch (IOException | ParseException | ModelBuildingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package io.github.spencerpark.ijava.magics.dependencies;
|
||||
|
||||
import org.apache.ivy.plugins.resolver.DependencyResolver;
|
||||
import org.apache.ivy.plugins.resolver.IBiblioResolver;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class CommonRepositories {
|
||||
protected static final String MAVEN_PATTERN_PREFIX = "[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier])";
|
||||
protected static final String MAVEN_ARTIFACT_PATTERN = MAVEN_PATTERN_PREFIX + ".[ext]";
|
||||
protected static final String MAVEN_POM_PATTERN = MAVEN_PATTERN_PREFIX + ".pom";
|
||||
|
||||
public static DependencyResolver maven(String name, String urlRaw) {
|
||||
IBiblioResolver resolver = new IBiblioResolver();
|
||||
resolver.setM2compatible(true);
|
||||
resolver.setUseMavenMetadata(true);
|
||||
resolver.setUsepoms(true);
|
||||
|
||||
resolver.setRoot(urlRaw);
|
||||
resolver.setName(name);
|
||||
|
||||
return resolver;
|
||||
}
|
||||
|
||||
public static DependencyResolver mavenCentral() {
|
||||
return CommonRepositories.maven("maven-central", "https://repo.maven.apache.org/maven2/");
|
||||
}
|
||||
|
||||
public static DependencyResolver jcenter() {
|
||||
return CommonRepositories.maven("jcenter", "https://jcenter.bintray.com/");
|
||||
}
|
||||
|
||||
public static DependencyResolver mavenLocal() {
|
||||
IBiblioResolver resolver = new IBiblioResolver();
|
||||
resolver.setM2compatible(true);
|
||||
resolver.setUseMavenMetadata(true);
|
||||
resolver.setUsepoms(true);
|
||||
|
||||
resolver.setName("maven-local");
|
||||
|
||||
Path localRepoPath;
|
||||
try {
|
||||
localRepoPath = Maven.getInstance().getConfiguredLocalRepositoryPath();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error reading maven settings. " + e.getLocalizedMessage(), e);
|
||||
} catch (SAXException e) {
|
||||
throw new RuntimeException("Error parsing maven settings. " + e.getLocalizedMessage(), e);
|
||||
}
|
||||
|
||||
resolver.setRoot("file:///" + localRepoPath.toString());
|
||||
|
||||
return resolver;
|
||||
}
|
||||
}
|
@ -0,0 +1,214 @@
|
||||
package io.github.spencerpark.ijava.magics.dependencies;
|
||||
|
||||
import org.apache.maven.building.StringSource;
|
||||
import org.apache.maven.model.building.*;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Maven {
|
||||
private static final Pattern MAVEN_VAR_PATTERN = Pattern.compile("\\$\\{(?<name>[^}*])}");
|
||||
|
||||
private static final Maven INSTANCE = new Maven(new Properties(), Collections.emptyMap());
|
||||
|
||||
public static Maven getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
// User provider environment overrides.
|
||||
private final Properties properties;
|
||||
private final Map<String, String> environment;
|
||||
|
||||
public Maven(Properties properties, Map<String, String> environment) {
|
||||
this.properties = properties;
|
||||
this.environment = environment;
|
||||
}
|
||||
|
||||
private String getProperty(String name, String def) {
|
||||
String val = this.environment.get(name);
|
||||
if (val != null)
|
||||
return val;
|
||||
|
||||
val = System.getProperty(name);
|
||||
return val != null ? val : def;
|
||||
}
|
||||
|
||||
private String getProperty(String name) {
|
||||
return this.getProperty(name, null);
|
||||
}
|
||||
|
||||
private String getEnv(String name, String def) {
|
||||
String val = this.environment.get(name);
|
||||
if (val != null)
|
||||
return val;
|
||||
|
||||
val = System.getenv(name);
|
||||
return val != null ? val : def;
|
||||
}
|
||||
|
||||
private String getEnv(String name) {
|
||||
return this.getEnv(name, null);
|
||||
}
|
||||
|
||||
public Path getUserSystemHomePath() {
|
||||
String home = this.getProperty("user.home");
|
||||
return Paths.get(home).toAbsolutePath();
|
||||
}
|
||||
|
||||
private String replaceMavenVars(String raw) {
|
||||
StringBuilder replaced = new StringBuilder();
|
||||
|
||||
Matcher matcher = MAVEN_VAR_PATTERN.matcher(raw);
|
||||
while (matcher.find())
|
||||
matcher.appendReplacement(replaced,
|
||||
System.getProperty(matcher.group("name"), ""));
|
||||
|
||||
matcher.appendTail(replaced);
|
||||
|
||||
return replaced.toString();
|
||||
}
|
||||
|
||||
// Thanks gradle!
|
||||
|
||||
private Path getUserHomePath() {
|
||||
return this.getUserSystemHomePath().resolve(".m2");
|
||||
}
|
||||
|
||||
private Path getGlobalHomePath() {
|
||||
String envM2Home = this.getEnv("M2_HOME");
|
||||
return envM2Home != null
|
||||
? Paths.get(envM2Home).toAbsolutePath() : null;
|
||||
}
|
||||
|
||||
private Path getUserSettingsPath() {
|
||||
return this.getUserHomePath().resolve("settings.xml");
|
||||
}
|
||||
|
||||
private Path getGlobalSettingsPath() {
|
||||
Path sysHome = this.getGlobalHomePath();
|
||||
return sysHome != null ? sysHome.resolve("conf").resolve("settings.xml") : null;
|
||||
}
|
||||
|
||||
private Path getDefaultLocalRepoPath() {
|
||||
return this.getUserHomePath().resolve("repository");
|
||||
}
|
||||
|
||||
private Path readConfiguredLocalRepositoryPath(Path settingsXmlPath) throws IOException, SAXException {
|
||||
if (!Files.isRegularFile(settingsXmlPath))
|
||||
return null;
|
||||
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
|
||||
DocumentBuilder builder;
|
||||
try {
|
||||
builder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
// We are configuring the factory, the configuration will be fine...
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
try (InputStream in = Files.newInputStream(settingsXmlPath)) {
|
||||
Document settingsDoc = builder.parse(in);
|
||||
NodeList settings = settingsDoc.getElementsByTagName("settings");
|
||||
if (settings.getLength() == 0)
|
||||
return null;
|
||||
|
||||
for (int i = 0; i < settings.getLength(); i++) {
|
||||
Node setting = settings.item(i);
|
||||
switch (setting.getNodeName()) {
|
||||
case "localRepository":
|
||||
String localRepository = setting.getTextContent();
|
||||
localRepository = this.replaceMavenVars(localRepository);
|
||||
return Paths.get(localRepository);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO just use the effective settings
|
||||
public Path getConfiguredLocalRepositoryPath() throws IOException, SAXException {
|
||||
Path userSettingsXmlPath = this.getUserSettingsPath();
|
||||
Path path = this.readConfiguredLocalRepositoryPath(userSettingsXmlPath);
|
||||
|
||||
if (path == null) {
|
||||
Path globalSettingsXmlPath = this.getGlobalSettingsPath();
|
||||
if (globalSettingsXmlPath != null)
|
||||
path = this.readConfiguredLocalRepositoryPath(globalSettingsXmlPath);
|
||||
}
|
||||
|
||||
return path == null ? this.getDefaultLocalRepoPath() : path;
|
||||
}
|
||||
|
||||
/*public SettingsBuildingResult readEffectiveSettings() throws SettingsBuildingException {
|
||||
DefaultSettingsBuilder settingsBuilder = new DefaultSettingsBuilderFactory().newInstance();
|
||||
|
||||
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
|
||||
|
||||
request.setSystemProperties(System.getProperties());
|
||||
request.setUserProperties(this.properties);
|
||||
|
||||
request.setUserSettingsFile(this.getUserSettingsPath().toFile());
|
||||
|
||||
Path globalSettingsPath = this.getGlobalSettingsPath();
|
||||
request.setGlobalSettingsFile(globalSettingsPath != null ? globalSettingsPath.toFile() : null);
|
||||
|
||||
return settingsBuilder.build(request);
|
||||
}*/
|
||||
|
||||
public ModelBuildingResult readEffectiveModel(CharSequence pom) throws ModelBuildingException {
|
||||
return this.readEffectiveModel(req ->
|
||||
req.setModelSource((ModelSource) new StringSource(pom))
|
||||
);
|
||||
}
|
||||
|
||||
public ModelBuildingResult readEffectiveModel(File pom) throws ModelBuildingException {
|
||||
return this.readEffectiveModel(req ->
|
||||
req.setPomFile(pom)
|
||||
);
|
||||
}
|
||||
|
||||
private ModelBuildingResult readEffectiveModel(Function<ModelBuildingRequest, ModelBuildingRequest> configuration) throws ModelBuildingException {
|
||||
DefaultModelBuilder modelBuilder = new DefaultModelBuilderFactory().newInstance();
|
||||
|
||||
ModelBuildingRequest request = new DefaultModelBuildingRequest();
|
||||
|
||||
request.setSystemProperties(System.getProperties());
|
||||
request.setUserProperties(this.properties);
|
||||
|
||||
// Allow force selection of active profile
|
||||
// request.setActiveProfileIds()
|
||||
// request.setInactiveProfileIds()
|
||||
|
||||
// Better error messages for bad poms
|
||||
request.setLocationTracking(true);
|
||||
|
||||
// Don't run plugins, in most cases this is what we want. I don't know of any
|
||||
// that would affect the POM.
|
||||
request.setProcessPlugins(false);
|
||||
|
||||
request = configuration.apply(request);
|
||||
|
||||
return modelBuilder.build(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package io.github.spencerpark.ijava.magics.dependencies;
|
||||
|
||||
import org.apache.ivy.plugins.resolver.ChainResolver;
|
||||
import org.apache.ivy.plugins.resolver.DependencyResolver;
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.Repository;
|
||||
import org.apache.maven.model.building.ModelBuildingException;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MavenToIvy {
|
||||
public static List<DependencyResolver> getRepositoriesFromModel(CharSequence pom) throws ModelBuildingException {
|
||||
return MavenToIvy.getRepositoriesFromModel(Maven.getInstance().readEffectiveModel(pom).getEffectiveModel());
|
||||
}
|
||||
|
||||
public static List<DependencyResolver> getRepositoriesFromModel(File pom) throws ModelBuildingException {
|
||||
return MavenToIvy.getRepositoriesFromModel(Maven.getInstance().readEffectiveModel(pom).getEffectiveModel());
|
||||
}
|
||||
|
||||
public static List<DependencyResolver> getRepositoriesFromModel(Model model) {
|
||||
return model.getRepositories().stream()
|
||||
.map(MavenToIvy::convertRepository)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public static DependencyResolver convertRepository(Repository repository) {
|
||||
return CommonRepositories.maven(repository.getId(), repository.getUrl());
|
||||
}
|
||||
|
||||
public static ChainResolver createChainForModelRepositories(Model model) {
|
||||
ChainResolver resolver = new ChainResolver();
|
||||
|
||||
// Maven central is always an implicit repository.
|
||||
resolver.add(CommonRepositories.mavenCentral());
|
||||
|
||||
MavenToIvy.getRepositoriesFromModel(model).forEach(resolver::add);
|
||||
|
||||
return resolver;
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package io.github.spencerpark.ijava.runtime;
|
||||
|
||||
import io.github.spencerpark.ijava.JavaKernel;
|
||||
import io.github.spencerpark.jupyter.kernel.display.DisplayData;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class Display {
|
||||
public static DisplayData render(Object o) {
|
||||
JavaKernel kernel = Kernel.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
return kernel.getRenderer().render(o);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
public static DisplayData render(Object o, String... as) {
|
||||
JavaKernel kernel = Kernel.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
return kernel.getRenderer().renderAs(o, as);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
public static String display(Object o) {
|
||||
JavaKernel kernel = Kernel.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
DisplayData data = kernel.getRenderer().render(o);
|
||||
|
||||
String id = data.getDisplayId();
|
||||
if (id == null) {
|
||||
id = UUID.randomUUID().toString();
|
||||
data.setDisplayId(id);
|
||||
}
|
||||
|
||||
kernel.display(data);
|
||||
|
||||
return id;
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
public static String display(Object o, String... as) {
|
||||
JavaKernel kernel = Kernel.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
DisplayData data = kernel.getRenderer().renderAs(o, as);
|
||||
|
||||
String id = data.getDisplayId();
|
||||
if (id == null) {
|
||||
id = UUID.randomUUID().toString();
|
||||
data.setDisplayId(id);
|
||||
}
|
||||
|
||||
kernel.display(data);
|
||||
|
||||
return id;
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateDisplay(String id, Object o) {
|
||||
JavaKernel kernel = Kernel.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
DisplayData data = kernel.getRenderer().render(o);
|
||||
kernel.getIO().display.updateDisplay(id, data);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
public static void updateDisplay(String id, Object o, String... as) {
|
||||
JavaKernel kernel = Kernel.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
DisplayData data = kernel.getRenderer().renderAs(o, as);
|
||||
kernel.getIO().display.updateDisplay(id, data);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package io.github.spencerpark.ijava.runtime;
|
||||
|
||||
import io.github.spencerpark.ijava.IJava;
|
||||
import io.github.spencerpark.ijava.JavaKernel;
|
||||
|
||||
public class Kernel {
|
||||
public static JavaKernel getKernelInstance() {
|
||||
return IJava.getKernelInstance();
|
||||
}
|
||||
|
||||
public static Object eval(String expr) throws Exception {
|
||||
JavaKernel kernel = getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
return kernel.evalRaw(expr);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package io.github.spencerpark.ijava.runtime;
|
||||
|
||||
import io.github.spencerpark.ijava.IJava;
|
||||
import io.github.spencerpark.ijava.JavaKernel;
|
||||
import io.github.spencerpark.jupyter.kernel.magic.registry.UndefinedMagicException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Magics {
|
||||
public static <T> T lineMagic(String name, List<String> args) {
|
||||
JavaKernel kernel = IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
try {
|
||||
return kernel.getMagics().applyLineMagic(name, args);
|
||||
} catch (UndefinedMagicException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format("Exception occurred while running line magic '%s': %s", name, e.getMessage()), e);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
public static <T> T cellMagic(String name, List<String> args, String body) {
|
||||
JavaKernel kernel = IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
try {
|
||||
return kernel.getMagics().applyCellMagic(name, args, body);
|
||||
} catch (UndefinedMagicException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format("Exception occurred while running cell magic '%s': %s", name, e.getMessage()), e);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,81 +0,0 @@
|
||||
io.github.spencerpark.jupyter.kernel.display.DisplayData render(Object o) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
return kernel.getRenderer().render(o);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
io.github.spencerpark.jupyter.kernel.display.DisplayData render(Object o, String... as) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
return kernel.getRenderer().renderAs(o, as);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
String display(Object o) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
io.github.spencerpark.jupyter.kernel.display.DisplayData data = kernel.getRenderer().render(o);
|
||||
|
||||
String id = data.getDisplayId();
|
||||
if (id == null) {
|
||||
id = java.util.UUID.randomUUID().toString();
|
||||
data.setDisplayId(id);
|
||||
}
|
||||
|
||||
kernel.display(data);
|
||||
|
||||
return id;
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
String display(Object o, String... as) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
io.github.spencerpark.jupyter.kernel.display.DisplayData data = kernel.getRenderer().renderAs(o, as);
|
||||
|
||||
String id = data.getDisplayId();
|
||||
if (id == null) {
|
||||
id = java.util.UUID.randomUUID().toString();
|
||||
data.setDisplayId(id);
|
||||
}
|
||||
|
||||
kernel.display(data);
|
||||
|
||||
return id;
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
void updateDisplay(String id, Object o) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
io.github.spencerpark.jupyter.kernel.display.DisplayData data = kernel.getRenderer().render(o);
|
||||
kernel.getIO().display.updateDisplay(id, data);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
void updateDisplay(String id, Object o, String... as) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
io.github.spencerpark.jupyter.kernel.display.DisplayData data = kernel.getRenderer().renderAs(o, as);
|
||||
kernel.getIO().display.updateDisplay(id, data);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
Object eval(String expr) throws Exception {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
return kernel.evalRaw(expr);
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
@ -6,6 +6,10 @@ import java.util.concurrent.*;
|
||||
import java.util.prefs.*;
|
||||
import java.util.regex.*;
|
||||
|
||||
import static io.github.spencerpark.ijava.runtime.Display.*;
|
||||
import static io.github.spencerpark.ijava.runtime.Kernel.*;
|
||||
import static io.github.spencerpark.ijava.runtime.Magics.*;
|
||||
|
||||
public void printf(String format, Object... args) {
|
||||
System.out.printf(format, args);
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
<T> T lineMagic(String name, java.util.List<String> args) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
try {
|
||||
return kernel.getMagics().applyLineMagic(name, args);
|
||||
} catch (io.github.spencerpark.jupyter.kernel.magic.registry.UndefinedMagicException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format("Exception occurred while running line magic '%s': %s", name, e.getMessage()), e);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
||||
|
||||
<T> T cellMagic(String name, java.util.List<String> args, String body) {
|
||||
io.github.spencerpark.ijava.JavaKernel kernel = io.github.spencerpark.ijava.IJava.getKernelInstance();
|
||||
|
||||
if (kernel != null) {
|
||||
try {
|
||||
return kernel.getMagics().applyCellMagic(name, args, body);
|
||||
} catch (io.github.spencerpark.jupyter.kernel.magic.registry.UndefinedMagicException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(String.format("Exception occurred while running cell magic '%s': %s", name, e.getMessage()), e);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("No IJava kernel running");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user