Small fixes

This commit is contained in:
Christopher Schnick 2022-01-02 23:13:10 +01:00
parent 8bb6f8be3d
commit e5a84a83db
15 changed files with 120 additions and 37 deletions

View file

@ -1,6 +1,7 @@
package io.xpipe.api;
import io.xpipe.beacon.*;
import io.xpipe.core.util.JacksonHelper;
import java.util.Optional;
@ -10,14 +11,8 @@ public abstract class XPipeApiConnector extends BeaconConnector {
try {
var socket = constructSocket();
handle(socket);
} catch (ConnectorException ce) {
throw new XPipeConnectException(ce.getMessage());
} catch (ClientException ce) {
throw new XPipeClientException(ce.getMessage());
} catch (ServerException se) {
throw new XPipeServerException(se.getMessage());
} catch (Throwable t) {
throw new XPipeConnectException(t);
} catch (Throwable ce) {
throw new XPipeException(ce);
}
}
@ -25,6 +20,10 @@ public abstract class XPipeApiConnector extends BeaconConnector {
@Override
protected BeaconClient constructSocket() throws ConnectorException {
if (!JacksonHelper.isInit()) {
JacksonHelper.init(ModuleLayer.boot());
}
if (!BeaconServer.isRunning()) {
try {
start();

View file

@ -0,0 +1,23 @@
package io.xpipe.api;
public class XPipeException extends RuntimeException {
public XPipeException() {
}
public XPipeException(String message) {
super(message);
}
public XPipeException(String message, Throwable cause) {
super(message, cause);
}
public XPipeException(Throwable cause) {
super(cause);
}
public XPipeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View file

@ -46,8 +46,13 @@ public abstract class DataSourceImpl implements DataSource {
@Override
protected void handle(BeaconClient sc) throws ClientException, ServerException, ConnectorException {
var req = StoreResourceExchange.Request.builder()
.url(url).type(type).build();
StoreResourceExchange.Response res = performSimpleExchange(sc, req);
.url(url).providerId(type).build();
StoreResourceExchange.Response res = performOutputExchange(sc, req, out -> {
try (var s = url.openStream()) {
writeLength(sc, s.available());
s.transferTo(out);
}
});
switch (res.getSourceType()) {
case TABLE -> {
var data = res.getTableData();

View file

@ -6,6 +6,7 @@ import io.xpipe.beacon.message.ResponseMessage;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicReference;
public abstract class BeaconConnector {
@ -40,6 +41,10 @@ public abstract class BeaconConnector {
return response.get();
}
protected void writeLength(BeaconClient socket, int bytes) throws IOException {
socket.getOutputStream().write(ByteBuffer.allocate(4).putInt(bytes).array());
}
protected <REQ extends RequestMessage, RES extends ResponseMessage> RES performSimpleExchange(
BeaconClient socket,
REQ req) throws ServerException, ConnectorException, ClientException {

View file

@ -10,7 +10,7 @@ public interface BeaconHandler {
void prepareBody() throws IOException;
void startBodyRead() throws IOException;
InputStream startBodyRead() throws IOException;
public <T extends ResponseMessage> void sendResponse(T obj) throws Exception;

View file

@ -33,7 +33,7 @@ public class StoreResourceExchange implements MessageExchange<StoreResourceExcha
@Value
public static class Request implements RequestMessage {
URL url;
String type;
String providerId;
}
@Jacksonized

View file

@ -26,5 +26,6 @@ module io.xpipe.beacon {
ReadInfoExchange,
StatusExchange,
StopExchange,
StoreResourceExchange,
VersionExchange;
}

View file

@ -12,6 +12,8 @@ import lombok.Getter;
* converted to lower case names when creating them.
* The two names are separated by a colon and are therefore not allowed to contain colons themselves.
*
* A missing collection name indicates that the data source exists only temporarily.
*
* @see #create(String, String)
* @see #fromString(String)
*/
@ -31,18 +33,15 @@ public class DataSourceId {
/**
* Creates a new data source id from a collection name and an entry name.
*
* @param collectionName the collection name, which must be not null and not empty
* @param collectionName the collection name, which may be null but not an empty string
* @param entryName the entry name, which must be not null and not empty
* @throws IllegalArgumentException if any name is not valid
*/
public static DataSourceId create(String collectionName, String entryName) {
if (collectionName == null) {
throw new IllegalArgumentException("Collection name is null");
}
if (collectionName.trim().length() == 0) {
if (collectionName != null && collectionName.trim().length() == 0) {
throw new IllegalArgumentException("Trimmed collection name is empty");
}
if (collectionName.contains("" + SEPARATOR)) {
if (collectionName != null && collectionName.contains("" + SEPARATOR)) {
throw new IllegalArgumentException("Separator character " + SEPARATOR + " is not allowed in the collection name");
}
@ -78,9 +77,7 @@ public class DataSourceId {
var cn = split[0].trim().toLowerCase();
var en = split[1].trim().toLowerCase();
if (cn.length() == 0) {
throw new IllegalArgumentException("Collection name must not be empty");
}
cn = cn.isEmpty() ? null : cn;
if (en.length() == 0) {
throw new IllegalArgumentException("Entry name must not be empty");
}

View file

@ -44,4 +44,8 @@ public class JacksonHelper {
return INSTANCE.copy();
}
public static boolean isInit() {
return init;
}
}

View file

@ -1,5 +1,7 @@
package io.xpipe.extension;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Path;
import java.util.Optional;
import java.util.ServiceLoader;
@ -41,6 +43,19 @@ public class DataSourceProviders {
return ALL.stream().filter(d -> d.supportsFile(file)).findAny();
}
public static Optional<DataSourceProvider> byURL(URL url) {
if (ALL == null) {
throw new IllegalStateException("Not initialized");
}
try {
var path = Path.of(url.toURI());
return byFile(path);
} catch (URISyntaxException e) {
return Optional.empty();
}
}
public static Set<DataSourceProvider> getAll() {
return ALL;
}

View file

@ -36,24 +36,24 @@ sourceSets {
java {
srcDir(projectDir)
srcDir("$rootDir/api/src/main/java")
srcDir("../api/src/main/java")
exclude {
return it.getFile() == file("$rootDir/api/src/main/java/module-info.java")
return it.getFile() == file("../api/src/main/java/module-info.java")
}
srcDir("$rootDir/core/src/main/java")
srcDir("../core/src/main/java")
exclude {
return it.getFile() == file("$rootDir/core/src/main/java/module-info.java")
return it.getFile() == file("../core/src/main/java/module-info.java")
}
srcDir("$rootDir/beacon/src/main/java")
srcDir("../beacon/src/main/java")
exclude {
return it.getFile() == file("$rootDir/beacon/src/main/java/module-info.java")
return it.getFile() == file("../beacon/src/main/java/module-info.java")
}
srcDir("$rootDir/extension/src/main/java")
srcDir("../extension/src/main/java")
exclude {
return it.getFile() == file("$rootDir/extension/src/main/java/module-info.java")
return it.getFile() == file("../extension/src/main/java/module-info.java")
}
}
}

View file

@ -1,9 +1,40 @@
module io.xpipe {
// api
exports io.xpipe.api;
// beacon
exports io.xpipe.beacon;
exports io.xpipe.beacon.exchange;
exports io.xpipe.beacon.message;
opens io.xpipe.beacon;
opens io.xpipe.beacon.exchange;
opens io.xpipe.beacon.message;
uses io.xpipe.beacon.exchange.MessageExchange;
provides io.xpipe.beacon.exchange.MessageExchange with
io.xpipe.beacon.exchange.ListCollectionsExchange,
io.xpipe.beacon.exchange.ListEntriesExchange,
io.xpipe.beacon.exchange.ReadTableDataExchange,
io.xpipe.beacon.exchange.ReadInfoExchange,
io.xpipe.beacon.exchange.StatusExchange,
io.xpipe.beacon.exchange.StopExchange,
io.xpipe.beacon.exchange.StoreResourceExchange,
io.xpipe.beacon.exchange.VersionExchange;
// core
exports io.xpipe.core.store;
exports io.xpipe.core.source;
exports io.xpipe.core.data.generic;
exports io.xpipe.core.data.type;
exports io.xpipe.core.data.node;
exports io.xpipe.core.util;
exports io.xpipe.core.data.typed;
opens io.xpipe.core.store;
opens io.xpipe.core.source;
opens io.xpipe.core.data.typed;
// core services
uses com.fasterxml.jackson.databind.Module;
provides com.fasterxml.jackson.databind.Module with io.xpipe.core.util.CoreJacksonModule;
requires com.fasterxml.jackson.core;
requires com.fasterxml.jackson.databind;
@ -11,8 +42,4 @@ module io.xpipe {
requires static lombok;
requires static javafx.base;
requires static javafx.graphics;
opens io.xpipe.beacon;
opens io.xpipe.beacon.exchange;
opens io.xpipe.beacon.message;
}

View file

@ -11,8 +11,15 @@ java {
repositories {
mavenCentral()
}
apply from: "$rootDir/deps/jackson.gradle"
dependencies {
implementation project(':api')
implementation project(':core')
implementation files(project(':library').jar.archivePath)
}
compileJava.dependsOn(project(':library').jar)
application {
mainModule = 'io.xpipe.sample'
mainClass = 'io.xpipe.sample.HomePricesSample'
}

View file

@ -17,7 +17,7 @@ public class HomePricesSample {
// Note that while this is possible, it is not recommended as
// all queries are routed through the XPipe client anyway.
// It allows us however to bundle the data with this sample program.
homePricesTable = DataSource.wrap(resource).asTable();
homePricesTable = DataSource.wrap(resource, "csv").asTable();
// As we didn't pass any configuration parameters, X-Pipe will try to automatically detect
// the correct configuration parameters. You can access these parameters like this:

View file

@ -1,3 +1,3 @@
module io.xpipe.sample {
requires io.xpipe.api;
requires io.xpipe;
}