Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions bolt/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com)

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.

SPDX-FileCopyrightText: 2021-present Arcade Data Ltd (info@arcadedata.com)
SPDX-License-Identifier: Apache-2.0
-->
<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>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-parent</artifactId>
<version>26.2.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>arcadedb-bolt</artifactId>
<packaging>jar</packaging>
<name>ArcadeDB BOLT Protocol</name>
<description>Neo4j BOLT wire protocol implementation for ArcadeDB</description>

<properties>
<neo4j-driver.version>5.27.0</neo4j-driver.version>
</properties>

<dependencies>
<dependency>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-server</artifactId>
<version>${project.parent.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.neo4j.driver</groupId>
<artifactId>neo4j-java-driver</artifactId>
<version>${neo4j-driver.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-test-utils</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>
91 changes: 91 additions & 0 deletions bolt/src/main/java/com/arcadedb/bolt/BoltChunkedInput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com)
*
* 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.
*
* SPDX-FileCopyrightText: 2021-present Arcade Data Ltd (info@arcadedata.com)
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.bolt;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
* Handles chunked message framing for BOLT protocol input.
* Messages are received as: [chunk_size (2 bytes)][chunk_data]...[0x00 0x00]
*/
public class BoltChunkedInput {
private final DataInputStream in;

public BoltChunkedInput(final InputStream in) {
this.in = new DataInputStream(in);
}

/**
* Read a complete message by dechunking.
* Reads chunks until a zero-length chunk is encountered.
*/
public byte[] readMessage() throws IOException {
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();

while (true) {
// Read chunk size (2 bytes, big-endian)
final int chunkSize = in.readUnsignedShort();

if (chunkSize == 0) {
// End of message
break;
}

// Read chunk data
final byte[] chunk = new byte[chunkSize];
in.readFully(chunk);
buffer.write(chunk);
}

return buffer.toByteArray();
}

/**
* Read raw bytes directly (for handshake).
*/
public byte[] readRaw(final int length) throws IOException {
final byte[] data = new byte[length];
in.readFully(data);
return data;
}

/**
* Read raw int (for handshake).
*/
public int readRawInt() throws IOException {
return in.readInt();
}

/**
* Read raw unsigned short (for chunk sizes).
*/
public int readRawShort() throws IOException {
return in.readUnsignedShort();
}

/**
* Check if data is available.
*/
public int available() throws IOException {
return in.available();
}
}
82 changes: 82 additions & 0 deletions bolt/src/main/java/com/arcadedb/bolt/BoltChunkedOutput.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com)
*
* 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.
*
* SPDX-FileCopyrightText: 2021-present Arcade Data Ltd (info@arcadedata.com)
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.bolt;

import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
* Handles chunked message framing for BOLT protocol.
* Messages are sent as: [chunk_size (2 bytes)][chunk_data]...[0x00 0x00]
*/
public class BoltChunkedOutput {
private static final int MAX_CHUNK_SIZE = 65535;

private final DataOutputStream out;

public BoltChunkedOutput(final OutputStream out) {
this.out = new DataOutputStream(out);
}

/**
* Write a complete message with chunked framing.
*/
public void writeMessage(final byte[] messageData) throws IOException {
int offset = 0;
final int length = messageData.length;

while (offset < length) {
final int chunkSize = Math.min(length - offset, MAX_CHUNK_SIZE);

// Write chunk header (2-byte size, big-endian)
out.writeShort(chunkSize);

// Write chunk data
out.write(messageData, offset, chunkSize);

offset += chunkSize;
}

// Write end marker (two zero bytes)
out.writeShort(0);
out.flush();
}

/**
* Write raw bytes directly (for handshake).
*/
public void writeRaw(final byte[] data) throws IOException {
out.write(data);
out.flush();
}

/**
* Write raw int (for handshake version response).
*/
public void writeRawInt(final int value) throws IOException {
out.writeInt(value);
out.flush();
}

public void flush() throws IOException {
out.flush();
}
}
61 changes: 61 additions & 0 deletions bolt/src/main/java/com/arcadedb/bolt/BoltException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com)
*
* 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.
*
* SPDX-FileCopyrightText: 2021-present Arcade Data Ltd (info@arcadedata.com)
* SPDX-License-Identifier: Apache-2.0
*/
package com.arcadedb.bolt;

import com.arcadedb.exception.ArcadeDBException;

/**
* Exception for BOLT protocol errors.
*/
public class BoltException extends ArcadeDBException {
private final String errorCode;

public BoltException(final String message) {
super(message);
this.errorCode = "Neo.DatabaseError.General.UnknownError";
}

public BoltException(final String errorCode, final String message) {
super(message);
this.errorCode = errorCode;
}

public BoltException(final String message, final Throwable cause) {
super(message, cause);
this.errorCode = "Neo.DatabaseError.General.UnknownError";
}

public BoltException(final String errorCode, final String message, final Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}

public String getErrorCode() {
return errorCode;
}

// Common Neo4j error codes
public static final String AUTHENTICATION_ERROR = "Neo.ClientError.Security.Unauthorized";

Check notice on line 54 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L54

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
public static final String SYNTAX_ERROR = "Neo.ClientError.Statement.SyntaxError";

Check notice on line 55 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L55

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
public static final String SEMANTIC_ERROR = "Neo.ClientError.Statement.SemanticError";

Check notice on line 56 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L56

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
public static final String DATABASE_ERROR = "Neo.DatabaseError.General.UnknownError";

Check notice on line 57 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L57

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
public static final String TRANSACTION_ERROR = "Neo.ClientError.Transaction.TransactionNotFound";

Check notice on line 58 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L58

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
public static final String FORBIDDEN_ERROR = "Neo.ClientError.Security.Forbidden";

Check notice on line 59 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L59

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
public static final String PROTOCOL_ERROR = "Neo.ClientError.Request.Invalid";

Check notice on line 60 in bolt/src/main/java/com/arcadedb/bolt/BoltException.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

bolt/src/main/java/com/arcadedb/bolt/BoltException.java#L60

Fields should be declared at the top of the class, before any method declarations, constructors, initializers or inner classes.
}
Loading
Loading