diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index ae11e6b..e38892a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -54,6 +54,45 @@ jobs: echo "error string found" fi + - name: Build Maven Plugin + run: | + mvn clean install --batch-mode + + - name: Integration tests with maven plugin + run: | + cd examples/maven_project_example + mvn compile --batch-mode + + cd allowed_types + set -x + mvn -q hibernate-provider:schema | tee maven_schema_output + diff maven_schema_output src/test/expected_default_schema + + mvn -q hibernate-provider:schema@schema-using-postgresql-properties | tee maven_psql_output + diff maven_psql_output src/test/expected_postgresql_output + + mvn -q hibernate-provider:schema -Dregistry-builder=com.example.H2ServiceRegistryBuilder | tee maven_h2_output + diff maven_h2_output src/test/expected_h2_output + + mvn -q hibernate-provider:schema -Dmetadata-builder=com.example.MetadataBuilder | tee maven_mini_output + diff maven_mini_output src/test/expected_mini_output + + mvn -q hibernate-provider:schema -Dpackages="com.example.model" | tee maven_employee_output + diff maven_employee_output src/test/expected_employee_output + + mvn -q hibernate-provider:schema -Dpackages="com.example.model" -Dclasses="com.example.minimodel.Location" | tee maven_classes_and_packages_output + diff maven_classes_and_packages_output src/test/expected_default_schema + + cd ../forbidden_types + if (set -o pipefail && atlas schema inspect --env hibernate --url env://src 2>&1 | tee /tmp/forbidden_output); then + echo "expected schema extraction to fail due to an unsupported SQL command" && false + else + echo "command failed successfully, checking output contains error string" + grep -i "unsupported GenerationType.SEQUENCE" /tmp/forbidden_output || (echo "Failed output comparison, output was:" && cat /tmp/forbidden_output && false) + echo "error string found" + fi + set +x + - uses: actions/setup-java@v3 with: distribution: zulu @@ -63,4 +102,10 @@ jobs: run: | cd examples/with_spring_gradle output=$(atlas migrate diff --env hibernate) - [ "$output" = "The migration directory is synced with the desired state, no changes to be made" ] || (echo "diff detected? unexpected output: $output"; ls -l migrations; exit 1) \ No newline at end of file + [ "$output" = "The migration directory is synced with the desired state, no changes to be made" ] || (echo "diff detected? unexpected output: $output"; ls -l migrations; exit 1) + + - name: E2E test maven project + run: | + cd examples/maven_project_example/allowed_types + output=$(atlas migrate diff --env hibernate) + [ "$output" = "The migration directory is synced with the desired state, no changes to be made" ] || (echo "diff detected? unexpected output: $output"; ls -l migrations; exit 1) diff --git a/.gitignore b/.gitignore index 9d3e546..94243ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ .local-plugin-repository +target diff --git a/build.gradle.kts b/build.gradle.kts index 49ee751..165b22a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -69,6 +69,11 @@ dependencies { testImplementation("org.hibernate.orm:hibernate-core:6.3.1.Final") testImplementation("com.h2database:h2:2.2.224") + // These are here for now just for editor support. The maven plugin is built using Maven + compileOnly("org.codehaus.mojo:exec-maven-plugin:3.1.1") + compileOnly("org.apache.maven:maven-plugin-api:3.6.3") + compileOnly("org.apache.maven:maven-project:2.2.1") + compileOnly("org.apache.maven.plugin-tools:maven-plugin-annotations:3.6.0") } tasks.test { diff --git a/examples/maven_project_example/allowed_types/atlas.hcl b/examples/maven_project_example/allowed_types/atlas.hcl new file mode 100644 index 0000000..176e9bc --- /dev/null +++ b/examples/maven_project_example/allowed_types/atlas.hcl @@ -0,0 +1,44 @@ +data "external_schema" "hibernate" { + program = [ + "mvn", + "-q", + "compile", + "hibernate-provider:schema" + ] +} + +data "external_schema" "hibernate_postgresql" { + program = [ + "mvn", + "-q", + "compile", + "hibernate-provider:schema", + "-Dproperties=postgresql.properties" + ] +} + +env "hibernate" { + src = data.external_schema.hibernate.url + dev = "docker://mysql/8/dev" + migration { + dir = "file://migrations" + } + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} + +env "hibernate_postgresql" { + src = data.external_schema.hibernate_postgresql.url + dev = "docker://postgres/15/dev" + migration { + dir = "file://migrations_postgresql" + } + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} diff --git a/examples/maven_project_example/allowed_types/migrations/20231205144835.sql b/examples/maven_project_example/allowed_types/migrations/20231205144835.sql new file mode 100644 index 0000000..a22d05a --- /dev/null +++ b/examples/maven_project_example/allowed_types/migrations/20231205144835.sql @@ -0,0 +1,21 @@ +-- Create "Location" table +CREATE TABLE `Location` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `title` varchar(255) NULL, + PRIMARY KEY (`id`) +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; +-- Create "Department" table +CREATE TABLE `Department` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL, + PRIMARY KEY (`id`) +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; +-- Create "Employee" table +CREATE TABLE `Employee` ( + `id` bigint NOT NULL AUTO_INCREMENT, + `name` varchar(255) NULL, + `department_id` bigint NULL, + PRIMARY KEY (`id`), + INDEX `FK14tijxqry9ml17nk86sqfp561` (`department_id`), + CONSTRAINT `FK14tijxqry9ml17nk86sqfp561` FOREIGN KEY (`department_id`) REFERENCES `Department` (`id`) ON UPDATE NO ACTION ON DELETE NO ACTION +) CHARSET utf8mb4 COLLATE utf8mb4_0900_ai_ci; diff --git a/examples/maven_project_example/allowed_types/migrations/atlas.sum b/examples/maven_project_example/allowed_types/migrations/atlas.sum new file mode 100644 index 0000000..55203fd --- /dev/null +++ b/examples/maven_project_example/allowed_types/migrations/atlas.sum @@ -0,0 +1,2 @@ +h1:Dy0V88s6slIfSnpV4kis08iLeJAYX1uFL1V5kHXZKHQ= +20231205144835.sql h1:nWzM/ZCeVTFmjjC8/0RmmpcD0KndYZjOKWm9BrqyhGs= diff --git a/examples/maven_project_example/allowed_types/pom.xml b/examples/maven_project_example/allowed_types/pom.xml new file mode 100644 index 0000000..409b72e --- /dev/null +++ b/examples/maven_project_example/allowed_types/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + maven_project_example + org.example + 1.0-SNAPSHOT + + + com.example.allowed + allowed_types + 1.0 + + allowed_types + + + UTF-8 + 11 + 11 + + + ${project.basedir}/src/main/java + + diff --git a/examples/maven_project_example/allowed_types/src/main/java/com/example/H2ServiceRegistryBuilder.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/H2ServiceRegistryBuilder.java new file mode 100644 index 0000000..278f4bb --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/main/java/com/example/H2ServiceRegistryBuilder.java @@ -0,0 +1,28 @@ +package com.example; + +import org.hibernate.boot.registry.StandardServiceRegistryBuilder; +import org.hibernate.cfg.AvailableSettings; +import org.hibernate.service.ServiceRegistry; + +import java.util.Map; +import java.util.Properties; +import java.util.function.Function; + +public class H2ServiceRegistryBuilder implements Function { + public H2ServiceRegistryBuilder() { + + } + + @Override + public ServiceRegistry apply(Properties properties) { + return new StandardServiceRegistryBuilder() + .applySettings(Map.of( + "hibernate.connection.url","jdbc:h2:mem:testdb", + AvailableSettings.SCHEMA_MANAGEMENT_TOOL, properties.get(AvailableSettings.SCHEMA_MANAGEMENT_TOOL), + "hibernate.temp.use_jdbc_metadata_defaults", true, + "jakarta.persistence.database-product-name", "H2", + "jakarta.persistence.database-major-version", "", + "hibernate.connection.provider_class", "")) + .build(); + } +} \ No newline at end of file diff --git a/examples/maven_project_example/src/main/java/com/example/HibernateUtil.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/HibernateUtil.java similarity index 100% rename from examples/maven_project_example/src/main/java/com/example/HibernateUtil.java rename to examples/maven_project_example/allowed_types/src/main/java/com/example/HibernateUtil.java diff --git a/examples/maven_project_example/allowed_types/src/main/java/com/example/Main.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/Main.java new file mode 100644 index 0000000..9b782ca --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/main/java/com/example/Main.java @@ -0,0 +1,30 @@ +package com.example; + +import com.example.minimodel.Location; +import com.example.model.Department; +import com.example.model.Employee; +import jakarta.persistence.Query; +import org.hibernate.Session; +import org.hibernate.Transaction; + +import java.util.List; + +public class Main { + public static void main(String[] args) { + System.out.println("Hello world"); + + Session session = HibernateUtil.getSessionFactory().openSession(); + Transaction transaction = session.beginTransaction(); + Location location = new Location(); + location.setTitle("Darkness"); + session.persist(location); + transaction.commit(); + Query q = session.createQuery("From Location ", Location.class); + List resultList = q.getResultList(); + System.out.println("num of locations:" + resultList.size()); + for (Location next : resultList) { + System.out.println("next location: (" + next.id + ") - " + next.title); + } + } + +} diff --git a/examples/maven_project_example/allowed_types/src/main/java/com/example/MetadataBuilder.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/MetadataBuilder.java new file mode 100644 index 0000000..f309d76 --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/main/java/com/example/MetadataBuilder.java @@ -0,0 +1,17 @@ +package com.example; + +import com.example.minimodel.Location; +import org.hibernate.boot.Metadata; +import org.hibernate.boot.MetadataSources; +import org.hibernate.service.ServiceRegistry; + +import java.util.function.Function; + +public class MetadataBuilder implements Function { + @Override + public Metadata apply(ServiceRegistry registry) { + return new MetadataSources(registry) + .addAnnotatedClasses(Location.class) + .buildMetadata(); + } +} diff --git a/examples/maven_project_example/allowed_types/src/main/java/com/example/minimodel/Location.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/minimodel/Location.java new file mode 100644 index 0000000..1f935d1 --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/main/java/com/example/minimodel/Location.java @@ -0,0 +1,31 @@ +package com.example.minimodel; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Location { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + public Long id; + + public String title = "hello"; + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/examples/maven_project_example/src/main/java/com/example/model/Department.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/model/Department.java similarity index 69% rename from examples/maven_project_example/src/main/java/com/example/model/Department.java rename to examples/maven_project_example/allowed_types/src/main/java/com/example/model/Department.java index eab64a4..cabc011 100644 --- a/examples/maven_project_example/src/main/java/com/example/model/Department.java +++ b/examples/maven_project_example/allowed_types/src/main/java/com/example/model/Department.java @@ -28,25 +28,12 @@ public class Department { public Department() { super(); } + public Department(String name) { this.name = name; } - public Long getId() { - return id; - } - public void setId(Long id) { - this.id = id; - } + public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - public List getEmployees() { - return employees; - } - public void setEmployees(List employees) { - this.employees = employees; - } } \ No newline at end of file diff --git a/examples/maven_project_example/src/main/java/com/example/model/Employee.java b/examples/maven_project_example/allowed_types/src/main/java/com/example/model/Employee.java similarity index 99% rename from examples/maven_project_example/src/main/java/com/example/model/Employee.java rename to examples/maven_project_example/allowed_types/src/main/java/com/example/model/Employee.java index 46722e7..923a2aa 100644 --- a/examples/maven_project_example/src/main/java/com/example/model/Employee.java +++ b/examples/maven_project_example/allowed_types/src/main/java/com/example/model/Employee.java @@ -3,7 +3,6 @@ import jakarta.persistence.*; @Entity -@Table public class Employee { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) diff --git a/examples/maven_project_example/src/main/resources/hibernate.cfg.xml b/examples/maven_project_example/allowed_types/src/main/resources/hibernate.cfg.xml similarity index 62% rename from examples/maven_project_example/src/main/resources/hibernate.cfg.xml rename to examples/maven_project_example/allowed_types/src/main/resources/hibernate.cfg.xml index aa40c06..9a8cc84 100644 --- a/examples/maven_project_example/src/main/resources/hibernate.cfg.xml +++ b/examples/maven_project_example/allowed_types/src/main/resources/hibernate.cfg.xml @@ -4,24 +4,23 @@ "http://www.hibernate.org/dtd/hibernate-configuration"> - - jdbc:mysql://localhost:3306/mydatabase - root - my-secret-pw - com.mysql.cj.jdbc.Driver + jdbc:postgresql://localhost:5432/postgres + postgres + password + org.postgresql.Driver true true true - create-drop - 1 + 3 thread + \ No newline at end of file diff --git a/examples/maven_project_example/allowed_types/src/main/resources/hibernate.properties b/examples/maven_project_example/allowed_types/src/main/resources/hibernate.properties new file mode 100644 index 0000000..019b4d7 --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/main/resources/hibernate.properties @@ -0,0 +1,2 @@ +jakarta.persistence.database-product-name=MySQL +jakarta.persistence.database-major-version=8 diff --git a/examples/maven_project_example/allowed_types/src/main/resources/postgresql.properties b/examples/maven_project_example/allowed_types/src/main/resources/postgresql.properties new file mode 100644 index 0000000..23898ef --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/main/resources/postgresql.properties @@ -0,0 +1 @@ +jakarta.persistence.database-product-name=PostgreSQL \ No newline at end of file diff --git a/examples/maven_project_example/allowed_types/src/test/expected_default_schema b/examples/maven_project_example/allowed_types/src/test/expected_default_schema new file mode 100644 index 0000000..30f46f0 --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/test/expected_default_schema @@ -0,0 +1,4 @@ +create table Department (id bigint not null auto_increment, name varchar(255), primary key (id)) engine=InnoDB; +create table Employee (id bigint not null auto_increment, name varchar(255), department_id bigint, primary key (id)) engine=InnoDB; +create table Location (id bigint not null auto_increment, title varchar(255), primary key (id)) engine=InnoDB; +alter table Employee add constraint FK14tijxqry9ml17nk86sqfp561 foreign key (department_id) references Department (id); diff --git a/examples/maven_project_example/allowed_types/src/test/expected_employee_output b/examples/maven_project_example/allowed_types/src/test/expected_employee_output new file mode 100644 index 0000000..42cc30f --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/test/expected_employee_output @@ -0,0 +1,3 @@ +create table Department (id bigint not null auto_increment, name varchar(255), primary key (id)) engine=InnoDB; +create table Employee (id bigint not null auto_increment, name varchar(255), department_id bigint, primary key (id)) engine=InnoDB; +alter table Employee add constraint FK14tijxqry9ml17nk86sqfp561 foreign key (department_id) references Department (id); diff --git a/examples/maven_project_example/allowed_types/src/test/expected_h2_output b/examples/maven_project_example/allowed_types/src/test/expected_h2_output new file mode 100644 index 0000000..6abbb13 --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/test/expected_h2_output @@ -0,0 +1,4 @@ +create table Department (id bigint generated by default as identity, name varchar(255), primary key (id)); +create table Employee (id bigint generated by default as identity, name varchar(255), department_id bigint, primary key (id)); +create table Location (id bigint generated by default as identity, title varchar(255), primary key (id)); +alter table Employee add constraint FK14tijxqry9ml17nk86sqfp561 foreign key (department_id) references Department; diff --git a/examples/maven_project_example/allowed_types/src/test/expected_mini_output b/examples/maven_project_example/allowed_types/src/test/expected_mini_output new file mode 100644 index 0000000..40f9dab --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/test/expected_mini_output @@ -0,0 +1 @@ +create table Location (id bigint not null auto_increment, title varchar(255), primary key (id)) engine=InnoDB; diff --git a/examples/maven_project_example/allowed_types/src/test/expected_postgresql_output b/examples/maven_project_example/allowed_types/src/test/expected_postgresql_output new file mode 100644 index 0000000..30f46f0 --- /dev/null +++ b/examples/maven_project_example/allowed_types/src/test/expected_postgresql_output @@ -0,0 +1,4 @@ +create table Department (id bigint not null auto_increment, name varchar(255), primary key (id)) engine=InnoDB; +create table Employee (id bigint not null auto_increment, name varchar(255), department_id bigint, primary key (id)) engine=InnoDB; +create table Location (id bigint not null auto_increment, title varchar(255), primary key (id)) engine=InnoDB; +alter table Employee add constraint FK14tijxqry9ml17nk86sqfp561 foreign key (department_id) references Department (id); diff --git a/examples/maven_project_example/allowed_types/src/test/expected_without_mini_output b/examples/maven_project_example/allowed_types/src/test/expected_without_mini_output new file mode 100644 index 0000000..e69de29 diff --git a/examples/maven_project_example/forbidden_types/atlas.hcl b/examples/maven_project_example/forbidden_types/atlas.hcl new file mode 100644 index 0000000..176e9bc --- /dev/null +++ b/examples/maven_project_example/forbidden_types/atlas.hcl @@ -0,0 +1,44 @@ +data "external_schema" "hibernate" { + program = [ + "mvn", + "-q", + "compile", + "hibernate-provider:schema" + ] +} + +data "external_schema" "hibernate_postgresql" { + program = [ + "mvn", + "-q", + "compile", + "hibernate-provider:schema", + "-Dproperties=postgresql.properties" + ] +} + +env "hibernate" { + src = data.external_schema.hibernate.url + dev = "docker://mysql/8/dev" + migration { + dir = "file://migrations" + } + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} + +env "hibernate_postgresql" { + src = data.external_schema.hibernate_postgresql.url + dev = "docker://postgres/15/dev" + migration { + dir = "file://migrations_postgresql" + } + format { + migrate { + diff = "{{ sql . \" \" }}" + } + } +} diff --git a/examples/maven_project_example/forbidden_types/pom.xml b/examples/maven_project_example/forbidden_types/pom.xml new file mode 100644 index 0000000..d0987a2 --- /dev/null +++ b/examples/maven_project_example/forbidden_types/pom.xml @@ -0,0 +1,24 @@ + + + 4.0.0 + + maven_project_example + org.example + 1.0-SNAPSHOT + + + com.example.forbidden + forbidden_types + 1.0 + + forbidden_types + + + UTF-8 + 11 + 11 + + + ${project.basedir}/src/main/java + + diff --git a/examples/maven_project_example/forbidden_types/src/main/java/com/example/forbidden/Location.java b/examples/maven_project_example/forbidden_types/src/main/java/com/example/forbidden/Location.java new file mode 100644 index 0000000..0cf8ac5 --- /dev/null +++ b/examples/maven_project_example/forbidden_types/src/main/java/com/example/forbidden/Location.java @@ -0,0 +1,31 @@ +package com.example.forbidden; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; + +@Entity +public class Location { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + public Long id; + + public String title = "hello"; + + public void setId(Long id) { + this.id = id; + } + + public Long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} diff --git a/examples/maven_project_example/forbidden_types/src/main/resources/hibernate.properties b/examples/maven_project_example/forbidden_types/src/main/resources/hibernate.properties new file mode 100644 index 0000000..019b4d7 --- /dev/null +++ b/examples/maven_project_example/forbidden_types/src/main/resources/hibernate.properties @@ -0,0 +1,2 @@ +jakarta.persistence.database-product-name=MySQL +jakarta.persistence.database-major-version=8 diff --git a/examples/maven_project_example/pom.xml b/examples/maven_project_example/pom.xml index c3ce661..9e1be1a 100644 --- a/examples/maven_project_example/pom.xml +++ b/examples/maven_project_example/pom.xml @@ -1,16 +1,15 @@ - 4.0.0 - org.example maven_project_example 1.0-SNAPSHOT + pom - 20 - 20 + 11 + 11 UTF-8 @@ -20,10 +19,78 @@ hibernate-core 6.2.13.Final + + + org.jetbrains.kotlin + kotlin-stdlib + 1.9.20 + compile + + mysql mysql-connector-java 8.0.33 + + + com.h2database + h2 + 2.2.224 + runtime + + + + org.postgresql + postgresql + 42.7.0 + + + + ${project.basedir}/src/main/kotlin + + + + org.jetbrains.kotlin + kotlin-maven-plugin + 1.9.20 + + + compile + + compile + + + + + + + + + + io.atlasgo + hibernate-provider-maven-plugin + 0.1 + + + schema-using-postgresq-properties + compile + + schema + + + postgresql.properties + + + + + + + + + + forbidden_types + allowed_types + \ No newline at end of file diff --git a/examples/maven_project_example/src/main/java/com/example/Main.java b/examples/maven_project_example/src/main/java/com/example/Main.java deleted file mode 100644 index e5e22f4..0000000 --- a/examples/maven_project_example/src/main/java/com/example/Main.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.example; - -import com.example.model.Department; -import com.example.model.Employee; -import jakarta.persistence.Query; -import org.hibernate.Session; - -import java.util.List; - -public class Main { - public static void main(String[] args) { - System.out.println("Hello world"); - - Session session = HibernateUtil.getSessionFactory().openSession(); - session.beginTransaction(); - Department department = new Department("java"); - session.persist(department); - session.persist(new Employee("Jakab Gipsz",department)); - session.persist(new Employee("Captain Nemo",department)); - session.getTransaction().commit(); - Query q = session.createQuery("From Employee ", Employee.class); - List resultList = q.getResultList(); - System.out.println("num of employees:" + resultList.size()); - for (Employee next : resultList) { - System.out.println("next employee: " + next); - } - } - -} diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..16a2ece --- /dev/null +++ b/pom.xml @@ -0,0 +1,105 @@ + + + 4.0.0 + io.atlasgo + hibernate-provider-maven-plugin + maven-plugin + 0.1 + + hibernate-provider-maven-plugin Maven Mojo + http://maven.apache.org + + + 11 + 11 + + + + + org.hibernate.orm + hibernate-core + 6.1.7.Final + compile + + + org.jetbrains.kotlin + kotlin-stdlib + 1.9.20 + compile + + + org.apache.maven + maven-plugin-api + 3.6.3 + provided + + + org.apache.maven.plugin-tools + maven-plugin-annotations + 3.6.0 + provided + + + org.apache.maven + maven-project + 2.2.1 + provided + + + com.github.ajalt.clikt + clikt-jvm + 4.2.1 + + + + + ${project.basedir}/src/main/kotlin + + + org.jetbrains.kotlin + kotlin-maven-plugin + 1.9.20 + + + + compile + + compile + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.4 + + + package + + shade + + + false + + + *:* + + + + + + + + + + + maven-plugin-plugin + 3.10.2 + + + + + \ No newline at end of file diff --git a/src/main/kotlin/HibernateProvider.kt b/src/main/kotlin/HibernateProvider.kt index b7827f3..0c44fee 100644 --- a/src/main/kotlin/HibernateProvider.kt +++ b/src/main/kotlin/HibernateProvider.kt @@ -248,4 +248,4 @@ class UnsupportedGenerationType(message: String): RuntimeException(message) { // and check manually if they were thrown val thrownExceptions = ConcurrentLinkedDeque() } -} \ No newline at end of file +} diff --git a/src/main/kotlin/MavenPlugin.kt b/src/main/kotlin/MavenPlugin.kt new file mode 100644 index 0000000..08bdd3f --- /dev/null +++ b/src/main/kotlin/MavenPlugin.kt @@ -0,0 +1,137 @@ +package io.atlasgo + +import org.apache.maven.artifact.Artifact +import org.apache.maven.plugin.AbstractMojo +import org.apache.maven.plugins.annotations.LifecyclePhase +import org.apache.maven.plugins.annotations.Mojo +import org.apache.maven.plugins.annotations.Parameter +import org.apache.maven.plugins.annotations.ResolutionScope +import org.apache.maven.project.MavenProject +import java.io.File +import java.lang.ProcessBuilder.Redirect +import java.nio.file.Path +import java.nio.file.Paths +import kotlin.system.exitProcess + +@Mojo(name = "schema", requiresDependencyResolution = ResolutionScope.RUNTIME, defaultPhase = LifecyclePhase.COMPILE) +internal class ExportSchemaMojo : AbstractMojo() { + @Parameter(defaultValue = "\${project}", required = true, readonly = true) + private lateinit var project: MavenProject + + @Parameter(property = "classpathScope", defaultValue = "runtime") + protected var classpathScope: String? = null + + @Parameter(property = "properties") + private val properties = "" + + @Parameter(property = "packages") + private var packages = emptyList() + + @Parameter(property = "classes") + private var classes = emptyList() + + @Parameter(property = "registry-builder") + private var registryBuilderClass = "" + + @Parameter(property = "metadata-builder") + private var metadataBuilderClass = "" + + @Parameter(property = "debug") + private var debugEnabled = false + + @Parameter(property = "enable-table-generators") + private var enableTableGenerators = false + + override fun execute() { + val args = mutableListOf("java") + if (debugEnabled) { + args += listOf("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005") + } + args += listOf("-cp", buildClasspath()) + args += ExportSchemaMain::class.java.name + if (registryBuilderClass.isNotBlank()) { + args += listOf("--registry-builder", registryBuilderClass) + } + if (properties.isNotBlank()) { + args += listOf("--properties", properties) + } + if (enableTableGenerators) { + args += "--enable-table-generators" + } + if (metadataBuilderClass.isEmpty()) { + if (classes.isNotEmpty()) { + args += listOf("--classes", classes.joinToString(",")) + } + if (scannedClasspath.isNotEmpty()) { + args += listOf("--packages", scannedClasspath.joinToString(",")) + } + } else { + args += listOf("--metadata-builder", metadataBuilderClass) + } + val exitCode = ProcessBuilder() + .command(args) + .redirectOutput(Redirect.INHERIT) + .redirectError(Redirect.INHERIT) + .start() + .waitFor() + if (exitCode != 0) { + exitProcess(exitCode) + } + } + + private val scannedClasspath: List by lazy { + val scanBase = File(project.build.outputDirectory) + val packageDirs = packages.map { it.replace(".", "/" )} + scanBase.walkBottomUp().filter { + it.isDirectory + }.filter { dir -> + packageDirs.isEmpty() || packageDirs.any { pack -> + dir.relativeTo(scanBase).startsWith(pack) + } + }.map { + it.toURI().toString().toBase64() + }.toList() + } + + private fun buildClasspath(): String { + val path = mutableListOf() + path.add(File(this::class.java.protectionDomain.codeSource.location.file).toPath()) + path += project.build.resources.map { + Paths.get(it.directory) + } + val artifacts = mutableListOf() + when (classpathScope) { + "compile" -> { + artifacts += project.compileArtifacts as List + path.add(Paths.get(project.build.outputDirectory)) + } + "test" -> { + artifacts += project.testArtifacts as List + path.add(Paths.get(project.build.testOutputDirectory)) + path.add(Paths.get(project.build.outputDirectory)) + } + "runtime" -> { + artifacts += project.runtimeArtifacts as List + path.add(Paths.get(project.build.outputDirectory)) + } + "system" -> { + artifacts += project.systemArtifacts as List + } + else -> { + throw IllegalStateException("Invalid classpath scope: $classpathScope") + } + } + path += artifacts.map { + it.file.toPath() + } + return path.joinToString(":") + } +} + +// Defining the main in a different class helps us avoid adding maven dependencies to the classpath +class ExportSchemaMain { + companion object { + @JvmStatic + fun main(args: Array) = PrintSchemaCommand().main(args) + } +}