В Cypher, Как изменить действующие протоколы URL для команды LOAD CSV
Этот вопрос состоит из двух частей:
По умолчанию, какие протоколы URL считаются действительными для указания ресурсов для Cypher
LOAD CSV
команда?- До сих пор я успешно загружал файлы CSV в Neo4j, используя http и файловые протоколы. Комментарий к этому несвязанному вопросу указывает, что ftp также работает, но я не пробовал этого, потому что у меня нет варианта использования.
Какие практические опции у меня есть для настройки нестандартных протоколов URI? Я работаю против Neo.TransientError.Statement.ExternalResourceFailure: с " Указан неверный URL (неизвестный протокол)". Кроме как копаться в источнике Neo4j, есть ли возможность изменить эту проверку / настройку, при условии, что хост-машина способна разрешить ресурс по указанному протоколу?
2 ответа
Neo4j опирается на возможности JVM. Согласно https://docs.oracle.com/javase/7/docs/api/java/net/URL.html протоколы по умолчанию:
http, https, ftp, file, jar
Обратите внимание, что
file
URL интерпретируются с точки зрения сервера, а не со стороны клиента (распространенный источник путаницы).Чтобы использовать пользовательские URL-адреса, вы должны понимать, как JVM справляется с ними. Класс javadocs для URL-адреса объясняет подход, используя системное свойство для предоставления пользовательских обработчиков URL-адресов. Это должно быть достаточно хорошо, чтобы предоставить это системное свойство в
neo4j-wrapper.conf
и поместите файл JAR, содержащий ваши классы обработчиков вplugins
папка. (Примечание: я не проверял этот подход сам, но я уверен, что он будет работать).
Вот полный пример, использующий технику реализации собственного
URLStreamHandler
вести протокол. Вы должны назвать свой класс «Handler», а последний сегмент имени пакета должен быть именем протокола (в данном случае
resource
)
src/main/java/com/example/protocols/resource/Handler.java
:
package com.example.protocols.resource;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
public class Handler extends URLStreamHandler {
private final ClassLoader classLoader;
public Handler() {
this.classLoader = getClass().getClassLoader();
}
@Override
protected URLConnection openConnection(URL url) throws IOException {
URL resource = classLoader.getResource(url.getPath());
if (resource == null) {
throw new FileNotFoundException("Resource file not found: " + url.getPath());
}
return resource.openConnection();
}
}
Отсюда нам нужно установить системное свойство, чтобы включить базовый пакет
com.example.protocols
чтобы протокол был зарегистрирован. Это можно сделать статически в Neo4j ExtensionFactory. Поскольку класс загружается Neo4j, мы знаем, что статический блок будет выполнен. Нам также необходимо предоставить собственное URLAccessRule, поскольку Neo4j по умолчанию разрешает использование только нескольких избранных протоколов. Это также может произойти в ExtensionFactory.
src/main/java/com/example/protocols/ProtocolInitializerFactory.java
:
package com.example.protocols;
import org.neo4j.annotations.service.ServiceProvider;
import org.neo4j.graphdb.security.URLAccessRule;
import org.neo4j.kernel.extension.ExtensionFactory;
import org.neo4j.kernel.extension.ExtensionType;
import org.neo4j.kernel.extension.context.ExtensionContext;
import org.neo4j.kernel.lifecycle.Lifecycle;
import org.neo4j.kernel.lifecycle.LifecycleAdapter;
@ServiceProvider
public class ProtocolInitializerFactory extends ExtensionFactory<ProtocolInitializerFactory.Dependencies> {
private static final String PROTOCOL_HANDLER_PACKAGES = "java.protocol.handler.pkgs";
private static final String PROTOCOL_PACKAGE = ProtocolInitializerFactory.class.getPackageName();
static {
String currentValue = System.getProperty(PROTOCOL_HANDLER_PACKAGES, "");
if (currentValue.isEmpty()) {
System.setProperty(PROTOCOL_HANDLER_PACKAGES, PROTOCOL_PACKAGE);
} else if (!currentValue.contains(PROTOCOL_PACKAGE)) {
System.setProperty(PROTOCOL_HANDLER_PACKAGES, currentValue + "|" + PROTOCOL_PACKAGE);
}
}
public interface Dependencies {
URLAccessRule urlAccessRule();
}
public ProtocolInitializerFactory() {
super(ExtensionType.DATABASE, "ProtocolInitializer");
}
@Override
public Lifecycle newInstance(ExtensionContext context, Dependencies dependencies) {
URLAccessRule urlAccessRule = dependencies.urlAccessRule();
return LifecycleAdapter.onInit(() -> {
URLAccessRule customRule = (config, url) -> {
if ("resource".equals(url.getProtocol())) { // Check the protocol name
return url; // Optionally, you can validate the URL here and throw an exception if it is not valid or should not be allowed access
}
return urlAccessRule.validate(config, url);
};
context.dependencySatisfier().satisfyDependency(customRule);
});
}
}
После настройки следуйте инструкциям по упаковке этих классов в качестве плагина Neo4j и поместите его в каталог плагинов вашей базы данных.
По общему признанию, необходимость переопределить URLAccessRule по умолчанию кажется немного сомнительной. Возможно, лучше просто реализовать URLStreamHandler и использовать другой метод загрузки CSV, например apoc.load.csv APOC . Это не потребует переопределения URLAccessRule, но потребует установки системного свойства Java.
java.protocol.handler.pkgs
.