Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,14 @@ codeconnect {
gradle -Dcodeconnect.connecttimeout=1000 reportUpstream
gradle -Dcodeconnect.upstream="log4j:log4j:4.12" showDownstream

mvn -f example-pom.xml reportUpstream
mvn -f example-pom.xml -Dcodeconnect.upstream="junit:junit:4.12" showDownstream

Maven reportUpstream can be performed without having to apply the plugin to your pom.xml:
mvn -Dcodeconnect.url="http://someserver:7474" -Dcodeconnect.username="neo4j" -Dcodeconnect.password="neo4j" com.toastedbits.plugins.codeconnect:codeconnect-maven-plugin:0.1.0-SNAPSHOT:reportUpstream

## TODO
* Drive the maven-plugin build with Gradle
* Write better tests
* Use a container (docker) to spin up neo4j for tests
* Use proper snapshot/release jar handling
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apply plugin: "maven"

version = "0.1.0-SNAPSHOT"
group = "com.toastedbits.codeconnect"
group = "com.toastedbits.plugins.codeconnect"

subprojects {
//maven plugin allows us to do gradle install and use mavenLocal() for the example script
Expand Down
2 changes: 1 addition & 1 deletion common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apply plugin: "eclipse"
apply plugin: "maven"

version = "0.1.0-SNAPSHOT"
group = "com.toastedbits.codeconnect"
group = "com.toastedbits.plugins.codeconnect"

dependencies {
compile "org.glassfish.jersey.core:jersey-client:2.17"
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.toastedbits.plugins.codeconnect.entities;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
Expand All @@ -9,7 +8,6 @@

import com.toastedbits.plugins.codeconnect.MavenCoordinate;
import com.toastedbits.plugins.codeconnect.exceptions.CodeConnectException;
import com.toastedbits.plugins.codeconnect.exceptions.Neo4jRestException;

public class Neo4jDownstreamResponseEntity {
private static final int GROUP_COL = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.toastedbits.plugins.codeconnect;
package com.toastedbits.plugins.codeconnect.neo4j;

import java.io.OutputStream;
import java.io.PrintWriter;
Expand All @@ -13,6 +13,8 @@
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import com.toastedbits.plugins.codeconnect.CodeConnectDownstreamReporter;
import com.toastedbits.plugins.codeconnect.MavenCoordinate;
import com.toastedbits.plugins.codeconnect.entities.Neo4jCypherPostEntity;
import com.toastedbits.plugins.codeconnect.entities.Neo4jDownstreamResponseEntity;
import com.toastedbits.plugins.codeconnect.exceptions.CodeConnectException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package com.toastedbits.plugins.codeconnect;
package com.toastedbits.plugins.codeconnect.neo4j;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand All @@ -14,6 +13,9 @@
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;

import com.toastedbits.plugins.codeconnect.CodeConnectUpstreamReporter;
import com.toastedbits.plugins.codeconnect.DependencyMapping;
import com.toastedbits.plugins.codeconnect.MavenCoordinate;
import com.toastedbits.plugins.codeconnect.entities.Neo4jTransactionPostEntity;
import com.toastedbits.plugins.codeconnect.entities.Neo4jTransactionStatement;
import com.toastedbits.plugins.codeconnect.exceptions.CodeConnectException;
Expand Down Expand Up @@ -49,61 +51,21 @@ public void reportUpstream(final DependencyMapping mapping, OutputStream output)

int transactionId = neo4j.beginTransaction(client);
resetNode(mapping.getProject(), transactionId);
reportDependencies(transactionId);
reportDependencies(mapping.getProject(), transactionId);
neo4j.commitTransaction(client, transactionId);
}
finally {
writer.flush();
}
}

private Map<String, String> buildNodeParameters(MavenCoordinate coordinate) {
Map<String, String> parameters = new LinkedHashMap<>();
parameters.put("projectName", coordinate.getArtifactId());
parameters.put("projectGroup", coordinate.getGroupId());
parameters.put("projectVersion", coordinate.getVersion());
return parameters;
}

private Neo4jTransactionStatement buildMergeStatement(MavenCoordinate coordinate) {
Neo4jTransactionStatement statement = new Neo4jTransactionStatement();
statement.setStatement("MERGE (proj:Project {name:{projectName}, group:{projectGroup}, version:{projectVersion}})");
statement.setParameters(buildNodeParameters(coordinate));
return statement;
}

private Neo4jTransactionStatement buildDeleteOutboundStatement() {
Neo4jTransactionStatement statement = new Neo4jTransactionStatement();
statement.setStatement("MATCH (down:Project {name:{projectName}, group:{projectGroup}, version:{projectVersion}})-[rel]->() DELETE rel");
statement.setParameters(buildNodeParameters(mapping.getProject()));
return statement;
}

private Neo4jTransactionStatement buildAssociationStatement(MavenCoordinate child, String configName, MavenCoordinate parent) {
Neo4jTransactionStatement statement = new Neo4jTransactionStatement();
//At time of writing, neo4j restApi does not support parameterization on relation name
statement.setStatement(
"MATCH (c:Project {name:{childName}, group:{childGroup}, version:{childVersion}}), " +
"(p:Project {name:{parentName}, group:{parentGroup}, version:{parentVersion}}) " +
"MERGE (c)-[:" + configName + "]->(p)");
Map<String, String> parameters = new LinkedHashMap<>();
parameters.put("childName", child.getArtifactId());
parameters.put("childGroup", child.getGroupId());
parameters.put("childVersion", child.getVersion());
parameters.put("parentName", parent.getArtifactId());
parameters.put("parentGroup", parent.getGroupId());
parameters.put("parentVersion", parent.getVersion());
statement.setParameters(parameters);
return statement;
}

private void resetNode(MavenCoordinate coordinate, int transactionId) throws CodeConnectException {
public void resetNode(MavenCoordinate coordinate, int transactionId) throws CodeConnectException {
writer.println("> Refreshing project node for: " +
coordinate.getGroupId() + ":" + coordinate.getArtifactId() + ":" + coordinate.getVersion());
Neo4jTransactionPostEntity payload = new Neo4jTransactionPostEntity();
List<Neo4jTransactionStatement> statements = new ArrayList<>();
statements.add(buildMergeStatement(coordinate));
statements.add(buildDeleteOutboundStatement());
statements.add(neo4j.buildMergeStatement(coordinate));
statements.add(neo4j.buildDeleteOutboundStatement(mapping.getProject()));
payload.setStatements(statements);

WebTarget target = client.target(baseUrl).path(Neo4jEndpoint.DB.Data.Transaction.path(transactionId));
Expand All @@ -114,7 +76,7 @@ private void resetNode(MavenCoordinate coordinate, int transactionId) throws Cod
}
}

private void reportDependencies(int transactionId) throws CodeConnectException {
public void reportDependencies(MavenCoordinate project, int transactionId) throws CodeConnectException {
for(Map.Entry<String, Set<MavenCoordinate>> configuration : mapping.getEntries()) {
String configName = configuration.getKey();
Set<MavenCoordinate> dependencies = configuration.getValue();
Expand All @@ -126,8 +88,8 @@ private void reportDependencies(int transactionId) throws CodeConnectException {
for(MavenCoordinate dependency : dependencies) {
writer.println("> (" + configName + ") " + dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion());

statements.add(buildMergeStatement(dependency));
statements.add(buildAssociationStatement(mapping.getProject(), configName, dependency));
statements.add(neo4j.buildMergeStatement(dependency));
statements.add(neo4j.buildAssociationStatement(project, configName, dependency));
}

WebTarget target = client.target(baseUrl).path(Neo4jEndpoint.DB.Data.Transaction.path(transactionId));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package com.toastedbits.plugins.codeconnect.neo4j;

import java.net.URI;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.toastedbits.plugins.codeconnect.MavenCoordinate;
import com.toastedbits.plugins.codeconnect.entities.Neo4jTransactionStatement;
import com.toastedbits.plugins.codeconnect.exceptions.Neo4jRestException;

public class Neo4jEndpoint {
private static final Logger LOG = LoggerFactory.getLogger(Neo4jEndpoint.class);

private final String baseUrl;

public Neo4jEndpoint(final Client client, final String baseUrl) {
this.baseUrl = baseUrl;
}

public static class DB {
public static String path() {
return "db";
}

public static class Data {
public static String path() {
return "db/data";
}

public static class Transaction {
public static String path() {
return "db/data/transaction";
}

public static String path(int id) {
return "db/data/transaction/" + id;
}

public static class Commit {
public static String path(int id) {
return "db/data/transaction/" + id + "/commit";
}
}
}

public static class Cypher {
public static String path() {
return "db/data/cypher";
}
}
}
}

public int beginTransaction(Client client) throws Neo4jRestException {
WebTarget target = client.target(baseUrl).path(DB.Data.Transaction.path());
Response response = target.request(MediaType.APPLICATION_JSON)
.post(null, Response.class);

if(response.getStatus() != HttpServletResponse.SC_CREATED) {
throw new Neo4jRestException("Failed to begin transaction, status code: " + response.getStatus());
}

URI location = response.getLocation();
String segments[] = location.toString().split("/");
return Integer.parseInt(segments[segments.length-1]);
}

public void commitTransaction(Client client, Integer id) throws Neo4jRestException {
LOG.debug("Committing Transaction");
WebTarget target = client.target(baseUrl).path(DB.Data.Transaction.Commit.path(id));
Response response = target.request(MediaType.APPLICATION_JSON)
.post(null, Response.class);

if(response.getStatus() != HttpServletResponse.SC_OK) {
throw new Neo4jRestException("Failed to commit transaction, status code: " + response.getStatus());
}
}

public Map<String, String> buildNodeParameters(MavenCoordinate coordinate) {
Map<String, String> parameters = new LinkedHashMap<>();
parameters.put("projectName", coordinate.getArtifactId());
parameters.put("projectGroup", coordinate.getGroupId());
parameters.put("projectVersion", coordinate.getVersion());
return parameters;
}

public Neo4jTransactionStatement buildMergeStatement(MavenCoordinate coordinate) {
Neo4jTransactionStatement statement = new Neo4jTransactionStatement();
statement.setStatement("MERGE (proj:Project {name:{projectName}, group:{projectGroup}, version:{projectVersion}})");
statement.setParameters(buildNodeParameters(coordinate));
return statement;
}

public Neo4jTransactionStatement buildDeleteOutboundStatement(MavenCoordinate project) {
Neo4jTransactionStatement statement = new Neo4jTransactionStatement();
statement.setStatement("MATCH (down:Project {name:{projectName}, group:{projectGroup}, version:{projectVersion}})-[rel]->() DELETE rel");
statement.setParameters(buildNodeParameters(project));
return statement;
}

public Neo4jTransactionStatement buildAssociationStatement(MavenCoordinate child, String configName, MavenCoordinate parent) {
Neo4jTransactionStatement statement = new Neo4jTransactionStatement();
//At time of writing, neo4j restApi does not support parameterization on relation name
statement.setStatement(
"MATCH (c:Project {name:{childName}, group:{childGroup}, version:{childVersion}}), " +
"(p:Project {name:{parentName}, group:{parentGroup}, version:{parentVersion}}) " +
"MERGE (c)-[:" + configName + "]->(p)");
Map<String, String> parameters = new LinkedHashMap<>();
parameters.put("childName", child.getArtifactId());
parameters.put("childGroup", child.getGroupId());
parameters.put("childVersion", child.getVersion());
parameters.put("parentName", parent.getArtifactId());
parameters.put("parentGroup", parent.getGroupId());
parameters.put("parentVersion", parent.getVersion());
statement.setParameters(parameters);
return statement;
}
}
Loading