package org.neo4j.jdbc.rest; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; import org.restlet.Client; import org.restlet.Context; import org.restlet.data.*; import org.restlet.resource.ClientResource; import org.restlet.util.Series; import java.io.IOException; import java.util.Collections; import java.util.List; /** * @author mh * @since 12.06.12 */ public class Resources { private ObjectMapper mapper = new ObjectMapper(); private final Reference ref; private String user; private String password; private final Client client; Resources(String url, Client client) { this.client = client; ref = new Reference(new Reference(url), "/"); } private Context createContext() { Context context = new Context(); context.setClientDispatcher(client); return context; } public void setAuth(String user, String password) { this.user = user; this.password = password; } public DiscoveryClientResource getDiscoveryResource() throws IOException { DiscoveryClientResource discovery = withAuth(new DiscoveryClientResource(createContext(), ref, mapper)); discovery.readInformation(); return discovery; } <T extends ClientResource> T withAuth(T resource) { if (hasAuth()) { resource.setChallengeResponse(ChallengeScheme.HTTP_BASIC, user, password); } return resource; } private boolean hasAuth() { return user != null && password != null; } public ClientResource getCypherResource(String cypherPath) { return withAuth(new CypherClientResource(new Context(), cypherPath, mapper)); } public JsonNode readJsonFrom(String uri) throws IOException { ClientResource resource = withAuth(new ClientResource(createContext(), uri)); resource.getClientInfo().setAcceptedMediaTypes(streamingJson()); return mapper.readTree(resource.get().getReader()); } private String textField(JsonNode node, String field) { final JsonNode fieldNode = node.get(field); if (fieldNode == null) return null; return fieldNode.getTextValue(); } public class DiscoveryClientResource extends ClientResource { private String version; private final ObjectMapper mapper; private String cypherPath; public DiscoveryClientResource(Context context, Reference ref, ObjectMapper mapper) { super(context, ref); this.mapper = mapper; getClientInfo().setAcceptedMediaTypes(streamingJson()); } public String getVersion() { return version; } public void readInformation() throws IOException { // Get service root JsonNode discoveryInfo = mapper.readTree(get().getReader()); final String dataUri = textField(discoveryInfo, "data"); JsonNode serverData = readJsonFrom(dataUri); version = textField(serverData, "neo4j_version"); cypherPath = obtainCypherPath(serverData); } private String obtainCypherPath(JsonNode serverData) { String cypherPath = textField(serverData, "cypher"); if (cypherPath == null) { final JsonNode extensions = serverData.get("extensions"); if (extensions != null) { final JsonNode plugin = extensions.get("CypherPlugin"); if (plugin != null) cypherPath = textField(plugin, "execute_query"); } } return cypherPath; } public String getCypherPath() { return cypherPath; } } private static class CypherClientResource extends ClientResource { private final ObjectMapper mapper; public CypherClientResource(final Context context, String cypherPath, ObjectMapper mapper) { super(context, cypherPath); this.mapper = mapper; getClientInfo().setAcceptedMediaTypes(streamingJson()); } @Override public void doError(Status errorStatus) { try { JsonNode node = mapper.readTree(getResponse().getEntity().getReader()); JsonNode message = node.get("message"); if (message != null) super.doError(new Status(errorStatus.getCode(), message.toString(), message.toString(), errorStatus.getUri())); } catch (IOException e) { // Ignore } super.doError(errorStatus); } } private static List<Preference<MediaType>> streamingJson() { final MediaType mediaType = streamingJsonType(); return Collections.singletonList(new Preference<MediaType>(mediaType)); } private static MediaType streamingJsonType() { final Series<Parameter> parameters = new Series<Parameter>(Parameter.class); parameters.add("stream", "true"); return new MediaType(MediaType.APPLICATION_JSON.getName(), parameters); } }