This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/maven-hocon-extension.git
commit 2fa97fad15db1ce560f76417a1b7f0905f0be708 Author: Guillaume Nodet <[email protected]> AuthorDate: Thu Sep 12 17:00:21 2024 +0200 Hocon extension --- .github/dependabot.yml | 28 +++ .github/workflows/maven-verify.yml | 31 ++++ .gitignore | 18 ++ README.md | 64 +++++++ pom.xml | 185 ++++++++++++++++++ src/it/hocon-example/.mvn/extensions.xml | 26 +++ src/it/hocon-example/child/pom.hocon | 35 ++++ src/it/hocon-example/pom.xml | 34 ++++ src/it/settings.xml | 25 +++ .../org/apache/maven/hocon/HoconModelParser.java | 63 +++++++ .../java/org/apache/maven/hocon/PathSource.java | 56 ++++++ src/main/resources/META-INF/maven/extension.xml | 27 +++ .../META-INF/maven/org.apache.maven.api.di.Inject | 17 ++ src/mdo/hocon-reader.vm | 206 +++++++++++++++++++++ .../java/org/apache/maven/hocon/ParsingTest.java | 42 +++++ src/test/resources/pom.hocon | 36 ++++ 16 files changed, 893 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ce41a74 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,28 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You 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. +# +version: 2 +updates: + + - package-ecosystem: maven + directory: "/" + schedule: + interval: daily + + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" \ No newline at end of file diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml new file mode 100644 index 0000000..99811aa --- /dev/null +++ b/.github/workflows/maven-verify.yml @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. + +name: Verify + +on: + push: + pull_request: + +jobs: + build: + name: Verify + uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4 + with: + ff-maven: "4.0.0-beta-4" # Maven version for fail-fast-build + maven-matrix: '[ "4.0.0-beta-4" ]' + jdk-matrix: '[ "17", "21" ]' diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e6cbeac --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +**/target/** +.project +.classpath +.settings/ +.svn/ +# Intellij +*.ipr +*.iml +.idea +.DS_Store +/bootstrap +/dependencies.xml +.java-version +.checkstyle +.factorypath +.vscode/ +repo/ +/*.svg \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c8a2eb --- /dev/null +++ b/README.md @@ -0,0 +1,64 @@ +<!--- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. +--> +[Apache Maven Hocon Extension](https://maven.apache.org/extensions/maven-xinclude-extension/) +================================== + +[](https://www.apache.org/licenses/LICENSE-2.0) +[](https://search.maven.org/artifact/org.apache.maven.extensions/maven-xinclude-extension) + +This project provides a Hocon POM parser extension for Maven 4. It allows POMs to +be written with the [Hocon](https://github.com/lightbend/config/blob/master/HOCON.md) +syntax, which is a superset of the [JSON](https://json.org/) syntax. + +License +------- +This code is under the [Apache License, Version 2.0, January 2004][license]. + +See the [`NOTICE`](./NOTICE) file for required notices and attributions. + +Usage +----- +To use this extension, the following declaration needs to be done in your `${rootDirectory}/.mvn/extensions.xml`: +``` +<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.2.0"> + <extension> + <groupId>org.apache.maven.extensions</groupId> + <artifactId>maven-hocon-extension</artifactId> + <version>@project.version@</version> + </extension> +</extensions> +``` +This allows defining a POM using Hocon syntax: +``` +modelVersion = 4.1.0 +parent { + groupId = org.apache.maven.hocon.its + artifactId = parent + version = 1.0.0-SNAPSHOT +} +artifactId = test + +properties = { + "my.property" = foo + pluginVersion = 3.9 +} + +dependencies = [ + # just add one dummy dependency + "com.typesafe:config:1.4.2" +] +``` diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..fc29277 --- /dev/null +++ b/pom.xml @@ -0,0 +1,185 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> +<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.maven.extensions</groupId> + <artifactId>maven-extensions</artifactId> + <version>43</version> + <relativePath /> + </parent> + + <artifactId>maven-hocon-extension</artifactId> + <version>1.0.0-SNAPSHOT</version> + <name>Hocon extension for Maven 4</name> + <description>Provides Hocon syntax support</description> + + <properties> + <javaVersion>17</javaVersion> + <maven.version>4.0.0-beta-4</maven.version> + <junit.version>5.11.0</junit.version> + <hocon.version>1.4.2</hocon.version> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-api-spi</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-api-core</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-api-di</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-api-impl</artifactId> + <version>${maven.version}</version> + </dependency> + <dependency> + <groupId>com.typesafe</groupId> + <artifactId>config</artifactId> + <version>${hocon.version}</version> + </dependency> + + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <version>${junit.version}</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <version>3.3.0</version> + <!-- Use the latest version of the plugin --> + <executions> + <execution> + <id>enforce-maven</id> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireMavenVersion> + <version>[4.0.0-beta-4,)</version> + <!-- Specify the required Maven version --> + <message>You need Maven 4.0.0-beta-4 or higher to build this project.</message> + </requireMavenVersion> + </rules> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <version>3.7.1</version> + <executions> + <execution> + <id>copy-mdo</id> + <goals> + <goal>copy</goal> + </goals> + <phase>generate-sources</phase> + <configuration> + <outputDirectory>${project.build.directory}/mdo</outputDirectory> + <artifact>org.apache.maven:maven-api-model:${maven.version}:mdo</artifact> + <stripVersion>true</stripVersion> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.modello</groupId> + <artifactId>modello-maven-plugin</artifactId> + <version>2.4.0</version> + <executions> + <execution> + <id>generate-hocon-reader</id> + <goals> + <goal>velocity</goal> + </goals> + <phase>generate-sources</phase> + <configuration> + <version>4.2.0</version> + <models> + <model>target/mdo/maven-api-model.mdo</model> + </models> + <templates> + <template>src/mdo/hocon-reader.vm</template> + </templates> + <params> + <param>packageModelV4=org.apache.maven.api.model</param> + </params> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.11.0</version> + <configuration> + <release>${javaVersion}</release> + <proc>full</proc> + </configuration> + </plugin> + </plugins> + </build> + + <profiles> + <profile> + <id>run-its</id> + <build> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-invoker-plugin</artifactId> + <version>3.8.0</version> + <configuration> + <showErrors>true</showErrors> + <cloneProjectsTo>${project.build.directory}/its</cloneProjectsTo> + <cloneClean>true</cloneClean> + <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath> + <settingsFile>src/it/settings.xml</settingsFile> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + </profile> + </profiles> + +</project> diff --git a/src/it/hocon-example/.mvn/extensions.xml b/src/it/hocon-example/.mvn/extensions.xml new file mode 100644 index 0000000..90ec8fc --- /dev/null +++ b/src/it/hocon-example/.mvn/extensions.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> +<extensions xmlns="http://maven.apache.org/EXTENSIONS/1.2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/EXTENSIONS/1.2.0 https://maven.apache.org/xsd/core-extensions-1.2.0.xsd"> + <extension> + <groupId>org.apache.maven.extensions</groupId> + <artifactId>maven-hocon-extension</artifactId> + <version>@project.version@</version> + </extension> +</extensions> \ No newline at end of file diff --git a/src/it/hocon-example/child/pom.hocon b/src/it/hocon-example/child/pom.hocon new file mode 100644 index 0000000..97c8295 --- /dev/null +++ b/src/it/hocon-example/child/pom.hocon @@ -0,0 +1,35 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# +modelVersion = 4.1.0 +parent { + groupId = org.apache.maven.hocon.its + artifactId = parent + version = 1.0.0-SNAPSHOT +} +artifactId = test + +properties = { + "my.property" = foo + pluginVersion = 3.9 +} + +dependencies = [ + # just add one dummy dependency + "com.typesafe:config:1.4.2" +] \ No newline at end of file diff --git a/src/it/hocon-example/pom.xml b/src/it/hocon-example/pom.xml new file mode 100644 index 0000000..c2c98ac --- /dev/null +++ b/src/it/hocon-example/pom.xml @@ -0,0 +1,34 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> +<project xmlns="http://maven.apache.org/POM/4.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.1.0 http://maven.apache.org/xsd/maven-4.1.0.xsd"> + <parent> + <groupId>org.apache.maven.extensions</groupId> + <artifactId>maven-extensions</artifactId> + <version>43</version> + </parent> + <groupId>org.apache.maven.hocon.its</groupId> + <artifactId>parent</artifactId> + <version>1.0.0-SNAPSHOT</version> + <packaging>pom</packaging> + + <modules> + <module>child</module> + </modules> +</project> diff --git a/src/it/settings.xml b/src/it/settings.xml new file mode 100644 index 0000000..0317296 --- /dev/null +++ b/src/it/settings.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> + +<settings xmlns="http://maven.apache.org/SETTINGS/1.3.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.3.0 https://maven.apache.org/xsd/settings-1.3.0.xsd"> +</settings> \ No newline at end of file diff --git a/src/main/java/org/apache/maven/hocon/HoconModelParser.java b/src/main/java/org/apache/maven/hocon/HoconModelParser.java new file mode 100644 index 0000000..fb3cb68 --- /dev/null +++ b/src/main/java/org/apache/maven/hocon/HoconModelParser.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.maven.hocon; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Map; +import java.util.Optional; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import org.apache.maven.api.di.Named; +import org.apache.maven.api.di.Priority; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.services.Source; +import org.apache.maven.api.spi.ModelParser; +import org.apache.maven.api.spi.ModelParserException; + +@Named("hocon") +@Priority(10) +public class HoconModelParser implements ModelParser { + + @Override + public Optional<Source> locate(Path path) { + Path pom = Files.isDirectory(path) ? path.resolve("pom.hocon") : path; + return Files.isRegularFile(pom) ? Optional.of(new PathSource(pom)) : Optional.empty(); + } + + @Override + public Model parse(Source source, Map<String, ?> map) throws ModelParserException { + Config config; + if (source.getPath() != null) { + config = ConfigFactory.parseFile(source.getPath().toFile()); + } else { + try (InputStream input = source.openStream()) { + config = ConfigFactory.parseReader(new InputStreamReader(input, StandardCharsets.UTF_8)); + } catch (IOException e) { + throw new ModelParserException("Unable to parse: " + source.getLocation(), e); + } + } + return new HoconReader().parseModel(config.root()); + } +} diff --git a/src/main/java/org/apache/maven/hocon/PathSource.java b/src/main/java/org/apache/maven/hocon/PathSource.java new file mode 100644 index 0000000..cdf5b7b --- /dev/null +++ b/src/main/java/org/apache/maven/hocon/PathSource.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.maven.hocon; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Objects; + +import org.apache.maven.api.services.Source; + +public class PathSource implements Source { + + private final Path path; + + public PathSource(Path path) { + this.path = Objects.requireNonNull(path); + } + + @Override + public Path getPath() { + return path; + } + + @Override + public InputStream openStream() throws IOException { + return Files.newInputStream(path); + } + + @Override + public String getLocation() { + return path.toString(); + } + + @Override + public Source resolve(String s) { + return new PathSource(path.resolve(s)); + } +} diff --git a/src/main/resources/META-INF/maven/extension.xml b/src/main/resources/META-INF/maven/extension.xml new file mode 100644 index 0000000..77ffe86 --- /dev/null +++ b/src/main/resources/META-INF/maven/extension.xml @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you 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. +--> +<!-- START SNIPPET: core-extension --> +<extension> + <exportedPackages> + <exportedPackage>org.apache.maven.hocon</exportedPackage> + <exportedPackage>META-INF.maven</exportedPackage> + </exportedPackages> +</extension> \ No newline at end of file diff --git a/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject b/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject new file mode 100644 index 0000000..6778661 --- /dev/null +++ b/src/main/resources/META-INF/maven/org.apache.maven.api.di.Inject @@ -0,0 +1,17 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +org.apache.maven.hocon.HoconModelParser diff --git a/src/mdo/hocon-reader.vm b/src/mdo/hocon-reader.vm new file mode 100644 index 0000000..b21925f --- /dev/null +++ b/src/mdo/hocon-reader.vm @@ -0,0 +1,206 @@ +#* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +*# +#set ( $package = "org.apache.maven.hocon" ) +#set ( $className = "HoconReader" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import org.apache.maven.api.annotations.Generated; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import com.typesafe.config.ConfigList; +import com.typesafe.config.ConfigObject; +import com.typesafe.config.ConfigValue; +import com.typesafe.config.ConfigValueType; + +@Generated +public class ${className} { + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + public ${classUcapName} parse${classUcapName}(ConfigValue value) { + if (value instanceof ConfigObject) { + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true); + ((ConfigObject) value).forEach((k, v) -> { + switch (k) { + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).transient && $field.name != "root" ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular( $fieldTagName ) ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}(getStringValue(v)); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}(getBooleanValue(v)); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}(getIntegerValue(v)); + break; + #elseif ( $field.type == "DOM" ) +// ${classLcapName}.${field.name}(XmlNodeBuilder.build(parser, true)); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + ${classLcapName}.${field.name}(getStringList(v)); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + ${classLcapName}.${field.name}(getStringMap(v)); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}(parse${field.toClass.name}(v)); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add(parse${field.toClass.name}(v)); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + ${classLcapName}.${field.name}(getList(v, this::parse${field.toClass.name})); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #end + #end + default: { + checkUnknownElement(k, v); + break; + } + } + }); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}(${field.name}); + #end + #end + return ${classLcapName}.build(); + #if($class.name=="Dependency") + } else if (value != null && value.valueType() == ConfigValueType.STRING) { + Dependency.Builder dependency = Dependency.newBuilder(true); + String[] tokens = ((String) value.unwrapped()).split(":"); + if (tokens.length < 3 || tokens.length > 5) { + throw new RuntimeException("Invalid artifact, you must specify " + + "groupId:artifactId:version[:packaging[:classifier]] " + value); + } + dependency.groupId(tokens[0]); + dependency.artifactId(tokens[1]); + dependency.version(tokens[2]); + if (tokens.length >= 4) { + dependency.type(tokens[3]); + } + if (tokens.length == 5) { + dependency.classifier(tokens[4]); + } + return dependency.build(); + #end + } else if (value != null) { + throw new IllegalArgumentException("Invalid syntax: cannot parse: " + value); + } + return null; + } + + #end +#end + + protected String getStringValue(ConfigValue v) { + return v.unwrapped().toString(); + } + + protected List<String> getStringList(ConfigValue v) { + if (v instanceof ConfigList) { + return ((ConfigList) v).unwrapped().stream().map(Object::toString) + .collect(Collectors.toList()); + } + throw new IllegalArgumentException("Unable to convert to List<String>: '" + v + "'"); + } + + protected boolean getBooleanValue(ConfigValue v) { + return Boolean.parseBoolean(v.unwrapped().toString()); + } + + protected int getIntegerValue(ConfigValue v) { + return Integer.parseInt(v.unwrapped().toString()); + } + + protected ConfigList getList(ConfigValue v) { + if (v instanceof ConfigList) { + return (ConfigList) v; + } + throw new IllegalArgumentException("Unable to convert to List<?>: '" + v + "'"); + } + + protected <T> List<T> getList(ConfigValue v, Function<ConfigValue, T> parser) { + return getList(v).stream().map(parser).collect(Collectors.toList()); + } + + protected Map<String, String> getStringMap(ConfigValue v) { + if (v instanceof ConfigObject) { + return ((ConfigObject) v).entrySet().stream().collect(Collectors.toMap( + e -> e.getKey(), + e -> getStringValue(e.getValue()) + )); + } + throw new IllegalArgumentException("Unable to convert to Map<String, String>: '" + v + "'"); + } + + protected void checkUnknownElement(String k, Object v) { + throw new IllegalArgumentException("Unrecognized element '" + k + "' with value '" + v + "'"); + } + +} diff --git a/src/test/java/org/apache/maven/hocon/ParsingTest.java b/src/test/java/org/apache/maven/hocon/ParsingTest.java new file mode 100644 index 0000000..6f611af --- /dev/null +++ b/src/test/java/org/apache/maven/hocon/ParsingTest.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.maven.hocon; + +import java.io.File; + +import com.typesafe.config.Config; +import com.typesafe.config.ConfigFactory; +import org.apache.maven.api.model.Model; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class ParsingTest { + + @Test + void testParse() throws Exception { + Config config = ConfigFactory.parseFile(new File("src/test/resources/pom.hocon")); + + Model model = new HoconReader().parseModel(config.root()); + + assertEquals("40", model.getParent().getVersion()); + assertEquals(1, model.getDependencies().size()); + assertEquals(2, model.getProperties().size()); + } +} diff --git a/src/test/resources/pom.hocon b/src/test/resources/pom.hocon new file mode 100644 index 0000000..c51b554 --- /dev/null +++ b/src/test/resources/pom.hocon @@ -0,0 +1,36 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you 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. +# +modelVersion = 4.0.0 +parent { + groupId = org.apache.maven.extensions + artifactId = maven-extensions + version = 40 +} +groupId = org.apache.maven.extensions +artifactId = maven-hocon-extension +version = 1.0.0-SNAPSHOT + +properties = { + "my.property" = foo + pluginVersion = 3.9 +} + +dependencies = [ + { groupId = org.apache.maven, artifactId = maven-api-core, version = 4.0.0-alpha-8-SNAPSHOT } +] \ No newline at end of file
