diff --git a/apache-maven/src/assembly/maven/bin/m2.conf b/apache-maven/src/assembly/maven/bin/m2.conf index c44656832dce..c050dc07bf1a 100644 --- a/apache-maven/src/assembly/maven/bin/m2.conf +++ b/apache-maven/src/assembly/maven/bin/m2.conf @@ -7,4 +7,5 @@ load ${maven.conf}/logging optionally ${maven.home}/lib/ext/redisson/*.jar optionally ${maven.home}/lib/ext/hazelcast/*.jar optionally ${maven.home}/lib/ext/*.jar +load ${maven.home}/lib/maven-*.jar load ${maven.home}/lib/*.jar diff --git a/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java b/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java index 70a11151fe53..7d1853b7a703 100644 --- a/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java +++ b/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java @@ -25,7 +25,7 @@ import java.io.Reader; import java.nio.charset.StandardCharsets; -import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader; +import org.apache.maven.settings.v4.SettingsXpp3Reader; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/api/maven-api-core/pom.xml b/api/maven-api-core/pom.xml new file mode 100644 index 000000000000..6ffef24727fc --- /dev/null +++ b/api/maven-api-core/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-core + Apache Maven Core API + + + + org.apache.maven + maven-api-meta + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-settings + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-toolchain + 4.0.0-alpha-1-SNAPSHOT + + + + diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java new file mode 100644 index 000000000000..5ebbc9783d0e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -0,0 +1,107 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +/** + * An artifact points to a resource such as a jar file or war application. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface Artifact +{ + + /** + * Returns a unique identifier for this artifact. + * The identifier is composed of groupId, artifactId, version, classifier, extension + * @return the unique identifier + */ + default String key() + { + return getGroupId() + + ':' + getArtifactId() + + ':' + getExtension() + + ( getClassifier().length() > 0 ? ":" + getClassifier() : "" ) + + ':' + getVersion(); + } + + /** + * The groupId of the artifact. + * + * @return The groupId. + */ + @Nonnull + String getGroupId(); + + /** + * The artifactId of the artifact. + * + * @return The artifactId. + */ + @Nonnull + String getArtifactId(); + + /** + * The version of the artifact. + * + * @return The version. + */ + @Nonnull + Version getVersion(); + + /** + * The classifier of the artifact. + * + * @return The classifier or an empty string if none, never {@code null}. + */ + @Nonnull + String getClassifier(); + + /** + * The file extension of the artifact. + * + * @return The extension. + */ + @Nonnull + String getExtension(); + + /** + * Determines whether this artifact uses a snapshot version. + * + * @return {@code true} if the artifact is a snapshot, {@code false} otherwise. + * @see org.apache.maven.api.Session#isVersionSnapshot(String) + */ + boolean isSnapshot(); + + /** + * Shortcut for {@code session.createArtifactCoordinate(artifact)} + * + * @return an {@link ArtifactCoordinate} + * @see org.apache.maven.api.Session#createArtifactCoordinate(Artifact) + */ + @Nonnull + ArtifactCoordinate toCoordinate(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinate.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinate.java new file mode 100644 index 000000000000..1f11e321986f --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinate.java @@ -0,0 +1,89 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +/** + * The {@code Coordinate} object is used to point to an {@link Artifact} + * but the version may be specified as a range instead of an exact version. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ArtifactCoordinate +{ + + /** + * The groupId of the artifact. + * + * @return The groupId. + */ + @Nonnull + String getGroupId(); + + /** + * The artifactId of the artifact. + * + * @return The artifactId. + */ + @Nonnull + String getArtifactId(); + + /** + * The classifier of the artifact. + * + * @return The classifier or an empty string if none, never {@code null}. + */ + @Nonnull + String getClassifier(); + + /** + * The version of the artifact. + * + * @return The version. + */ + @Nonnull + VersionRange getVersion(); + + /** + * The extension of the artifact. + * + * @return The extension or an empty string if none, never {@code null}. + */ + @Nonnull + String getExtension(); + + /** + * Unique id identifying this artifact + */ + default String getId() + { + return getGroupId() + + ":" + getArtifactId() + + ":" + getExtension() + + ( getClassifier().isEmpty() ? "" : ":" + getClassifier() ) + + ":" + getVersion(); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java new file mode 100644 index 000000000000..51fa632efcc8 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -0,0 +1,48 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +public interface Dependency extends Artifact +{ + + /** + * The artifact type. + * + * @return The artifact type, never {@code null}. + */ + @Nonnull + Type getType(); + + Scope getScope(); + + boolean isOptional(); + + /** + * Shortcut for {@code session.createDependencyCoordinate(dependency)} + * + * @return an {@link DependencyCoordinate} + * @see org.apache.maven.api.Session#createDependencyCoordinate(Dependency) + */ + @Nonnull + DependencyCoordinate toCoordinate(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/DependencyCoordinate.java b/api/maven-api-core/src/main/java/org/apache/maven/api/DependencyCoordinate.java new file mode 100644 index 000000000000..e5ea7a4cb6c2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/DependencyCoordinate.java @@ -0,0 +1,54 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.Immutable; + +import java.util.Collection; + +/** + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface DependencyCoordinate extends ArtifactCoordinate +{ + /** + * The type of the artifact. + * + * @return The type. + */ + @Nonnull + Type getType(); + + @Nonnull + Scope getScope(); + + @Nullable + Boolean getOptional(); + + @Nonnull + Collection getExclusions(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java new file mode 100644 index 000000000000..0a30dba8fd51 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java @@ -0,0 +1,77 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Optional; + +/** + * Event sent by maven during various phases of the build process. + * Such events can be listened to using {@link Listener}s objects + * registered in the {@link Session}. + * + * @since 4.0 + */ +@Experimental +public interface Event +{ + + /** + * Gets the type of the event. + * + * @return The type of the event, never {@code null}. + */ + @Nonnull + EventType getType(); + + /** + * Gets the session from which this event originates. + * + * @return The current session, never {@code null}. + */ + @Nonnull + Session getSession(); + + /** + * Gets the current project (if any). + * + * @return The current project or {@code empty()} if not applicable. + */ + @Nonnull + Optional getProject(); + + /** + * Gets the current mojo execution (if any). + * + * @return The current mojo execution or {@code empty()} if not applicable. + */ + @Nonnull + Optional getMojoExecution(); + + /** + * Gets the exception that caused the event (if any). + * + * @return The exception or {@code empty()} if none. + */ + Optional getException(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java new file mode 100644 index 000000000000..0279d1222573 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java @@ -0,0 +1,49 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The possible types of execution events. + * + * @since 4.0 + */ +@Experimental +public enum EventType +{ + PROJECT_DISCOVERY_STARTED, + SESSION_STARTED, + SESSION_ENDED, + PROJECT_SKIPPED, + PROJECT_STARTED, + PROJECT_SUCCEEDED, + PROJECT_FAILED, + MOJO_SKIPPED, + MOJO_STARTED, + MOJO_SUCCEEDED, + MOJO_FAILED, + FORK_STARTED, + FORK_SUCCEEDED, + FORK_FAILED, + FORKED_PROJECT_STARTED, + FORKED_PROJECT_SUCCEEDED, + FORKED_PROJECT_FAILED, +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java new file mode 100644 index 000000000000..143c6d257ae4 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java @@ -0,0 +1,40 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nullable; + +/** + * A dependency exlusion. + * + * @since 4.0 + * @see DependencyCoordinate#getExclusions() + */ +@Experimental +public interface Exclusion +{ + @Nullable + String getGroupId(); + + @Nullable + String getArtifactId(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java new file mode 100644 index 000000000000..21eefa49013f --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java @@ -0,0 +1,35 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * A specific {@link Toolchain} dedicated for Java. + * + * @since 4.0 + */ +@Experimental +public interface JavaToolchain extends Toolchain +{ + + String getJavaHome(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java new file mode 100644 index 000000000000..924ddaeaa6ed --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java @@ -0,0 +1,36 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A listener for session events. + * + * @since 4.0 + */ +@Experimental +@FunctionalInterface @Consumer +public interface Listener +{ + void onEvent( @Nonnull Event event ); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java new file mode 100644 index 000000000000..4d1101f7613d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java @@ -0,0 +1,42 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +/** + * The local repository is used to cache artifacts downloaded from {@link RemoteRepository} + * and to hold artifacts that have been build locally. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface LocalRepository extends Repository +{ + + @Nonnull + Path getPath(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java new file mode 100644 index 000000000000..d86aef64809c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java @@ -0,0 +1,41 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * TODO: investigate removing the Metadata api completely + * + * @since 4.0 + */ +@Experimental +public interface Metadata +{ + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + MetadataStorage getStorage(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java new file mode 100644 index 000000000000..1b988cfc7c5e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java @@ -0,0 +1,35 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * Storage location for metadata + * + * @since 4.0 + */ +@Experimental +public enum MetadataStorage +{ + GROUP, + ARTIFACT, + VERSION +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java new file mode 100644 index 000000000000..0d7ffd1a3499 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java @@ -0,0 +1,47 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.util.Optional; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.xml.Dom; + +/** + * A {@code MojoExecution} + */ +@Experimental +public interface MojoExecution +{ + @Nonnull + Plugin getPlugin(); + + @Nonnull + String getExecutionId(); + + @Nonnull + String getGoal(); + + @Nonnull + Optional getConfiguration(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java new file mode 100644 index 000000000000..f0bb78b17353 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java @@ -0,0 +1,103 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * Represents a dependency node within a Maven project's dependency collector. + * + * @since 4.0 + * @see org.apache.maven.api.services.DependencyCollectorResult#getRoot() + */ +@Experimental +@Immutable +public interface Node +{ + + /** + * @return dependency for this node + */ + Dependency getDependency(); + + /** + * Gets the child nodes of this node. + * + * @return the child nodes of this node, never {@code null} + */ + @Nonnull + List getChildren(); + + /** + * @return repositories of this node + */ + @Nonnull + List getRemoteRepositories(); + + /** + * The repository where this artifact has been downloaded from. + */ + @Nonnull + Optional getRepository(); + + /** + * Traverses this node and potentially its children using the specified visitor. + * + * @param visitor The visitor to call back, must not be {@code null}. + * @return {@code true} to visit siblings nodes of this node as well, {@code false} to skip siblings. + */ + boolean accept( @Nonnull NodeVisitor visitor ); + + /** + * Returns a new tree starting at this node, filtering the children. + * Note that this node will not be filtered and only the children + * and its descendant will be checked. + * + * @param filter the filter to apply + * @return a new filtered graph + */ + Node filter( Predicate filter ); + + /** + * Returns a string representation of this dependency node. + * + * @return the string representation + */ + String asString(); + + /** + * Obtain a Stream containing this node and all its descendant. + * + * @return a stream containing this node and its descendant + */ + @Nonnull + default Stream stream() + { + return Stream.concat( Stream.of( this ), getChildren().stream().flatMap( Node::stream ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java new file mode 100644 index 000000000000..39ae803eacdc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java @@ -0,0 +1,53 @@ +package org.apache.maven.api; + +/* + * 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. + */ + + +import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Defines a hierarchical visitor for collecting dependency node trees. + * + * @since 4.0 + */ +@Experimental +@Consumer +public interface NodeVisitor +{ + /** + * Starts the visit to the specified dependency node. + * + * @param node the dependency node to visit + * @return true to visit the specified dependency node's children, false to skip the + * specified dependency node's children and proceed to its next sibling + */ + boolean enter( @Nonnull Node node ); + + /** + * Ends the visit to the specified dependency node. + * + * @param node the dependency node to visit + * @return true to visit the specified dependency node's next sibling, false to skip the + * specified dependency node's next siblings and proceed to its parent + */ + boolean leave( @Nonnull Node node ); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java new file mode 100644 index 000000000000..0531724b12d8 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -0,0 +1,105 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; + +/** + * Interface representing a Maven project. + * Projects can be built using the {@link org.apache.maven.api.services.ProjectBuilder} service. + * + * @since 4.0 + */ +@Experimental +public interface Project +{ + + @Nonnull + String getGroupId(); + + @Nonnull + String getArtifactId(); + + @Nonnull + String getVersion(); + + @Nonnull + String getPackaging(); + + @Nonnull + Artifact getArtifact(); + + @Nonnull + Model getModel(); + + @Nonnull + default Build getBuild() + { + Build build = getModel().getBuild(); + return build != null ? build : Build.newInstance(); + } + + /** + * Returns the path to the pom file for this project. + * A project is usually read from the file system and this will point to + * the file. In some cases, a transient project can be created which + * will not point to an actual pom file. + * @return the path of the pom + */ + @Nonnull + Optional getPomPath(); + + @Nonnull + default Optional getBasedir() + { + return getPomPath().map( Path::getParent ); + } + + @Nonnull + List getDependencies(); + + @Nonnull + List getManagedDependencies(); + + @Nonnull + default String getId() + { + return getModel().getId(); + } + + boolean isExecutionRoot(); + + @Nonnull + Optional getParent(); + + @Nonnull + List getRemoteProjectRepositories(); + + @Nonnull + List getRemotePluginRepositories(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java new file mode 100644 index 000000000000..4dd629f2c59f --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java @@ -0,0 +1,40 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A remote repository that can be used to download or upload artifacts. + */ +@Experimental +@Immutable +public interface RemoteRepository extends Repository +{ + + @Nonnull + String getUrl(); + + @Nonnull + String getProtocol(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java new file mode 100644 index 000000000000..10551d737c5d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java @@ -0,0 +1,54 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A repository holds artifacts. + * + * @since 4.0 + * @see RemoteRepository + * @see LocalRepository + */ +@Experimental +@Immutable +public interface Repository +{ + + /** + * Gets the identifier of this repository. + * + * @return The (case-sensitive) identifier, never {@code null}. + */ + @Nonnull + String getId(); + + /** + * Gets the type of the repository, for example "default". + * + * @return The (case-sensitive) type of the repository, never {@code null}. + */ + @Nonnull + String getType(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java new file mode 100644 index 000000000000..a64879658bc8 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java @@ -0,0 +1,31 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * + * @since 4.0 + */ +@Experimental +public interface RepositoryMetadata extends Metadata +{ +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java new file mode 100644 index 000000000000..a68dc5256c02 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java @@ -0,0 +1,104 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Dependencies resolution scopes available before + * mojo execution. + * + * Important note: The {@code id} values of this enum correspond to constants of + * {@code org.apache.maven.artifact.Artifact} class and MUST BE KEPT IN SYNC. + * + * @since 4.0 + */ +@Experimental +public enum ResolutionScope +{ + /** + * empty resolution scope + */ + NONE( null ), + /** + * compile resolution scope + * = compile + system + provided dependencies + */ + COMPILE( "compile", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED ), + /** + * compile+runtime resolution scope (Maven 3 only) + * = compile + system + provided + runtime dependencies + */ + COMPILE_PLUS_RUNTIME( "compile+runtime", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED, Scope.RUNTIME ), + /** + * runtime resolution scope + * = compile + runtime dependencies + */ + RUNTIME( "runtime", Scope.COMPILE, Scope.RUNTIME ), + /** + * runtime+system resolution scope (Maven 3 only) + * = compile + system + runtime dependencies + */ + RUNTIME_PLUS_SYSTEM( "runtime+system", Scope.COMPILE, Scope.SYSTEM, Scope.RUNTIME ), + /** + * test resolution scope + * = compile + system + provided + runtime + test + * dependencies + */ + TEST( "test", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED, Scope.RUNTIME, Scope.TEST ); + + private static final Map VALUES + = Stream.of( ResolutionScope.values() ).collect( Collectors.toMap( ResolutionScope::id, s -> s ) ); + + public static ResolutionScope fromString( String id ) + { + return Optional.ofNullable( VALUES.get( id ) ) + .orElseThrow( () -> new IllegalArgumentException( "Unknown resolution scope " + id ) ); + } + + private final String id; + private final Set scopes; + + ResolutionScope( String id, Scope... scopes ) + { + this.id = id; + this.scopes = Collections.unmodifiableSet( new HashSet<>( Arrays.asList( scopes ) ) ); + } + + public String id() + { + return this.id; + } + + public Set scopes() + { + return scopes; + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Scope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Scope.java new file mode 100644 index 000000000000..f246e9fd7f5e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Scope.java @@ -0,0 +1,57 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.util.Locale; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Scope for a dependency + * + * @since 4.0 + */ +@Experimental +public enum Scope +{ + COMPILE( "compile" ), + PROVIDED ( "provided" ), + SYSTEM( "system" ), + RUNTIME( "runtime" ), + TEST( "test" ), + IMPORT( "import" ); + + private final String id; + + Scope( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } + + public static Scope get( String scope ) + { + return Enum.valueOf( Scope.class, scope.toUpperCase( Locale.ROOT ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java new file mode 100644 index 000000000000..a4cabcaa7b50 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java @@ -0,0 +1,37 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.ThreadSafe; + +/** + * Marker interface for all services provided by the {@link Session}. + *

+ * Services can be retrieved from the session using the + * {@link Session#getService(Class)} method. + * + * @see Session#getService(Class) + */ +@Experimental +@ThreadSafe +public interface Service +{ +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java new file mode 100644 index 000000000000..0d0cf07f9cb8 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -0,0 +1,346 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.time.Instant; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Properties; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.ThreadSafe; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.services.DependencyCoordinateFactory; +import org.apache.maven.api.settings.Settings; + +/** + * The session to install / deploy / resolve artifacts and dependencies. + * + * @since 4.0 + */ +@Experimental +@ThreadSafe +public interface Session +{ + + @Nonnull + Settings getSettings(); + + @Nonnull + LocalRepository getLocalRepository(); + + @Nonnull + List getRemoteRepositories(); + + @Nonnull + SessionData getData(); + + // TODO: investigate using Map or Map for all properties in the new API + @Nonnull + Properties getUserProperties(); + + @Nonnull + Properties getSystemProperties(); + + /** + * Returns the current maven version + * @return the maven version, never {@code null}. + */ + @Nonnull + String getMavenVersion(); + + int getDegreeOfConcurrency(); + + @Nonnull + Instant getStartTime(); + + @Nonnull + Path getMultiModuleProjectDirectory(); + + @Nonnull + Path getExecutionRootDirectory(); + + @Nonnull + List getProjects(); + + /** + * Returns the plugin context for mojo being executed and the specified + * {@link Project}, never returns {@code null} as if context not present, creates it. + * + * Implementation note: while this method return type is {@link Map}, the returned map instance + * implements {@link java.util.concurrent.ConcurrentMap} as well. + * + * @throws org.apache.maven.api.services.MavenException if not called from the within a mojo execution + */ + @Nonnull + Map getPluginContext( @Nonnull Project project ); + + /** + * Retrieves the service for the interface + * + * @throws NoSuchElementException if the service could not be found + */ + @Nonnull + T getService( @Nonnull Class clazz ); + + /** + * Creates a derived session using the given local repository. + * + * @param localRepository the new local repository + * @return the derived session + * @throws NullPointerException if {@code localRepository} is null + */ + @Nonnull + Session withLocalRepository( @Nonnull LocalRepository localRepository ); + + /** + * Creates a derived session using the given remote repositories. + * + * @param repositories the new list of remote repositories + * @return the derived session + * @throws NullPointerException if {@code repositories} is null + */ + @Nonnull + Session withRemoteRepositories( @Nonnull List repositories ); + + /** + * Register the given listener which will receive all events. + * + * @param listener the listener to register + * @throws NullPointerException if {@code listener} is null + */ + void registerListener( @Nonnull Listener listener ); + + /** + * Unregisters a previously registered listener. + * + * @param listener the listener to unregister + * @throws NullPointerException if {@code listener} is null + */ + void unregisterListener( @Nonnull Listener listener ); + + /** + * Returns the list of registered listeners. + * + * @return an immutable collection of listeners, never {@code null} + */ + @Nonnull + Collection getListeners(); + + /** + * Shortcut for getService(RepositoryFactory.class).createLocal(...) + * @see org.apache.maven.api.services.RepositoryFactory#createLocal(Path) + */ + LocalRepository createLocalRepository( Path path ); + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * @see org.apache.maven.api.services.RepositoryFactory#createRemote(String, String) + */ + @Nonnull + RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ); + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * @see org.apache.maven.api.services.RepositoryFactory#createRemote(Repository) + */ + @Nonnull + RemoteRepository createRemoteRepository( @Nonnull Repository repository ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) + */ + ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version, String extension ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version, String classifier, + String extension, String type ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + ArtifactCoordinate createArtifactCoordinate( Artifact artifact ); + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate) + */ + @Nonnull + DependencyCoordinate createDependencyCoordinate( @Nonnull ArtifactCoordinate coordinate ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) + */ + Artifact createArtifact( String groupId, String artifactId, String version, String extension ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + Artifact createArtifact( String groupId, String artifactId, String version, String classifier, + String extension, String type ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Artifact resolveArtifact( ArtifactCoordinate coordinate ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Collection resolveArtifacts( ArtifactCoordinate... coordinates ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Collection resolveArtifacts( Collection coordinates ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Artifact resolveArtifact( Artifact artifact ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Collection resolveArtifacts( Artifact... artifacts ); + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * @see org.apache.maven.api.services.ArtifactInstaller#install(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactInstallerException if the artifacts installation failed + */ + void installArtifacts( Artifact... artifacts ); + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * @see org.apache.maven.api.services.ArtifactInstaller#install(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactInstallerException if the artifacts installation failed + */ + void installArtifacts( Collection artifacts ); + + /** + * Shortcut for getService(ArtifactDeployer.class).deploy(...) + * @see org.apache.maven.api.services.ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + * + * @throws org.apache.maven.api.services.ArtifactDeployerException if the artifacts deployment failed + */ + void deployArtifact( RemoteRepository repository, Artifact... artifacts ); + + /** + * Shortcut for getService(ArtifactManager.class).setPath(...) + * @see org.apache.maven.api.services.ArtifactManager#setPath(Artifact, Path) + */ + void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ); + + /** + * Shortcut for getService(ArtifactManager.class).getPath(...) + * @see org.apache.maven.api.services.ArtifactManager#getPath(Artifact) + */ + @Nonnull + Optional getArtifactPath( @Nonnull Artifact artifact ); + + /** + * Shortcut for getService(ArtifactManager.class).isSnapshot(...) + * @see org.apache.maven.api.services.VersionParser#isSnapshot(String) + */ + boolean isVersionSnapshot( @Nonnull String version ); + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Artifact) + * + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed + */ + @Nonnull + Node collectDependencies( @Nonnull Artifact artifact ); + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Project) + * + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed + */ + @Nonnull + Node collectDependencies( @Nonnull Project project ); + + /** + * Shortcut for getService(DependencyResolver.class).resolve(...) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, DependencyCoordinate) + * + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed + */ + @Nonnull + Node collectDependencies( @Nonnull DependencyCoordinate dependency ); + + Path getPathForLocalArtifact( @Nonnull Artifact artifact ); + + Path getPathForLocalMetadata( Metadata metadata ); + + Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ); + + Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ); + + /** + * Shortcut for getService(VersionParser.class).parseVersion(...) + * @see org.apache.maven.api.services.VersionParser#parseVersion(String) + * + * @throws org.apache.maven.api.services.VersionParserException if the parsing failed + */ + @Nonnull + Version parseVersion( @Nonnull String version ); + + /** + * Shortcut for getService(VersionParser.class).parseVersionRange(...) + * @see org.apache.maven.api.services.VersionParser#parseVersionRange(String) + * + * @throws org.apache.maven.api.services.VersionParserException if the parsing failed + */ + @Nonnull + VersionRange parseVersionRange( @Nonnull String versionRange ); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java new file mode 100644 index 000000000000..8a8ef19401f0 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java @@ -0,0 +1,86 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.Provider; +import org.apache.maven.api.annotations.ThreadSafe; + +import java.util.function.Supplier; + +/** + * A container for data that is specific to a session. + * All components may use this storage to associate arbitrary data with a session. + *

+ * Unlike a cache, this session data is not subject to purging. For this same reason, session data should also not be + * abused as a cache (i.e. for storing values that can be re-calculated) to avoid memory exhaustion. + *

+ * Note: Actual implementations must be thread-safe. + * + * @see Session#getData() + * @since 4.0 + */ +@Experimental +@ThreadSafe @Provider +public interface SessionData +{ + + /** + * Associates the specified session data with the given key. + * + * @param key The key under which to store the session data, must not be {@code null}. + * @param value The data to associate with the key, may be {@code null} to remove the mapping. + */ + void set( @Nonnull Object key, @Nullable Object value ); + + /** + * Associates the specified session data with the given key if the key is currently mapped to the given value. This + * method provides an atomic compare-and-update of some key's value. + * + * @param key The key under which to store the session data, must not be {@code null}. + * @param oldValue The expected data currently associated with the key, may be {@code null}. + * @param newValue The data to associate with the key, may be {@code null} to remove the mapping. + * @return {@code true} if the key mapping was successfully updated from the old value to the new value, + * {@code false} if the current key mapping didn't match the expected value and was not updated. + */ + boolean set( @Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue ); + + /** + * Gets the session data associated with the specified key. + * + * @param key The key for which to retrieve the session data, must not be {@code null}. + * @return The session data associated with the key or {@code null} if none. + */ + @Nullable + Object get( @Nonnull Object key ); + + /** + * Retrieve of compute the data associated with the specified key. + * + * @param key The key for which to retrieve the session data, must not be {@code null}. + * @param supplier The supplier will compute the new value. + * @return The session data associated with the key. + */ + @Nullable + Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier supplier ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java new file mode 100644 index 000000000000..2f497194e33d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java @@ -0,0 +1,56 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.util.Map; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Toolchain interface. + * + * @since 4.0 + */ +@Experimental +public interface Toolchain +{ + /** + * get the type of toolchain. + * + * @return the toolchain type + */ + String getType(); + + /** + * Gets the platform tool executable. + * + * @param toolName the tool platform independent tool name. + * @return file representing the tool executable, or null if the tool can not be found + */ + String findTool( String toolName ); + + /** + * Let the toolchain decide if it matches requirements defined + * in the toolchain plugin configuration. + * @param requirements Map<String, String> key value pair, may not be {@code null} + * @return {@code true} if the requirements match, otherwise {@code false} + */ + boolean matchesRequirements( Map requirements ); +} \ No newline at end of file diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java new file mode 100644 index 000000000000..71a94b2e28fc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java @@ -0,0 +1,72 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; + +/** + * An artifact's{@code Type} represents a known kind of artifacts. + * Such types are often associated to an extension and possibly + * a classifier, for example {@code java-source} has a {@code jar} + * extension and a {@code sources} classifier. + * It is also used to determine if a given dependency should be + * included in the classpath or if its transitive dependencies should. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface Type +{ + + String POM = "pom"; + String JAR = "jar"; + String JAVA_SOURCE = "java-source"; + String JAVADOC = "javadoc"; + String MAVEN_PLUGIN = "maven-plugin"; + String TEST_JAR = "test-jar"; + + /** + * Returns the dependency type name. + * + * @return the type name + */ + String getName(); + + /** + * Get the file extension associated to the file represented by the dependency type. + * + * @return the file extension + */ + String getExtension(); + + /** + * Get the classifier associated to the dependency type. + * + * @return the classifier + */ + String getClassifier(); + + boolean isIncludesDependencies(); + + boolean isAddedToClasspath(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java new file mode 100644 index 000000000000..bf75f6c1d232 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java @@ -0,0 +1,46 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A version usually parsed using the {@link org.apache.maven.api.services.VersionParser} service. + * + * @since 4.0 + * @see org.apache.maven.api.services.VersionParser#parseVersion(String) + * @see org.apache.maven.api.Session#parseVersion(String) + */ +@Experimental +public interface Version + extends Comparable +{ + + // TODO: add access to the version information + + /** + * Returns a string representation of this version. + * @return the string representation of this version + */ + @Nonnull + String asString(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java new file mode 100644 index 000000000000..fb3e39b2f630 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java @@ -0,0 +1,50 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A range of versions. + * + * @since 4.0 + */ +@Experimental +public interface VersionRange +{ + + // TODO: add access to the version information + + /** + * Determines whether the specified version is contained within this range. + * + * @param version The version to test, must not be {@code null}. + * @return {@code true} if this range contains the specified version, {@code false} otherwise. + */ + boolean contains( @Nonnull Version version ); + + /** + * Returns a string representation of this version range + * @return the string representation of this version range + */ + @Nonnull + String asString(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java new file mode 100644 index 000000000000..f0eb2a660aaa --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java @@ -0,0 +1,168 @@ +package org.apache.maven.api.plugin; + +/* + * 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. + */ + +import java.util.function.Supplier; + +/** + * This interface supplies the API for providing feedback to the user from the Mojo, using standard + * Maven channels.
+ * There should be no big surprises here, although you may notice that the methods accept + * java.lang.CharSequence rather than java.lang.String. This is provided mainly as a + * convenience, to enable developers to pass things like java.lang.StringBuffer directly into the logger, + * rather than formatting first by calling toString(). + * + * @since 4.0 + */ +public interface Log +{ + /** + * @return true if the debug error level is enabled + */ + boolean isDebugEnabled(); + + /** + * Send a message to the user in the debug error level. + * + * @param content + */ + void debug( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the debug error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void debug( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the debug error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void debug( Throwable error ); + + void debug( Supplier content ); + + void debug( Supplier content, Throwable error ); + + /** + * @return true if the info error level is enabled + */ + boolean isInfoEnabled(); + + /** + * Send a message to the user in the info error level. + * + * @param content + */ + void info( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the info error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void info( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the info error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void info( Throwable error ); + + void info( Supplier content ); + + void info( Supplier content, Throwable error ); + + /** + * @return true if the warn error level is enabled + */ + boolean isWarnEnabled(); + + /** + * Send a message to the user in the warn error level. + * + * @param content + */ + void warn( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the warn error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void warn( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the warn error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void warn( Throwable error ); + + void warn( Supplier content ); + + void warn( Supplier content, Throwable error ); + + /** + * @return true if the error error level is enabled + */ + boolean isErrorEnabled(); + + /** + * Send a message to the user in the error error level. + * + * @param content + */ + void error( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the error error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void error( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the error error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void error( Throwable error ); + + void error( Supplier content ); + + void error( Supplier content, Throwable error ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java new file mode 100644 index 000000000000..a6217bff2a96 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java @@ -0,0 +1,46 @@ +package org.apache.maven.api.plugin; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; + +/** + * This interface forms the contract required for Mojos to interact with the Maven + * infrastructure.
+ * It features an execute() method, which triggers the Mojo's build-process behavior, and can throw + * a MojoException if error conditions occur.
+ * + * @since 4.0 + */ +@Experimental +@FunctionalInterface @Consumer +public interface Mojo +{ + /** + * Perform whatever build-process behavior this Mojo implements.
+ * This is the main trigger for the Mojo inside the Maven system, and allows + * the Mojo to communicate errors. + * + * @throws MojoException if a problem occurs. + */ + void execute(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java new file mode 100644 index 000000000000..5e5b0c7eee1c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java @@ -0,0 +1,98 @@ +package org.apache.maven.api.plugin; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.services.MavenException; + +/** + * An exception occurring during the execution of a plugin. + * + * @since 4.0 + */ +@Experimental +public class MojoException + extends MavenException +{ + + protected Object source; + + protected String longMessage; + + /** + * Construct a new MojoExecutionException exception providing the source and a short and long message: + * these messages are used to improve the message written at the end of Maven build. + */ + public MojoException( Object source, String shortMessage, String longMessage ) + { + super( shortMessage ); + this.source = source; + this.longMessage = longMessage; + } + + /** + * Construct a new MojoExecutionException exception wrapping an underlying Exception + * and providing a message. + */ + public MojoException( String message, Exception cause ) + { + super( message, cause ); + } + + /** + * Construct a new MojoExecutionException exception wrapping an underlying Throwable + * and providing a message. + */ + public MojoException( String message, Throwable cause ) + { + super( message, cause ); + } + + /** + * Construct a new MojoExecutionException exception providing a message. + */ + public MojoException( String message ) + { + super( message ); + } + + /** + * Constructs a new {@code MojoExecutionException} exception wrapping an underlying {@code Throwable}. + * + * @param cause the cause which is saved for later retrieval by the {@link #getCause()} method. + * A {@code null} value is permitted, and indicates that the cause is nonexistent or unknown. + * @since 3.8.3 + */ + public MojoException( Throwable cause ) + { + super( cause ); + } + + public String getLongMessage() + { + return longMessage; + } + + public Object getSource() + { + return source; + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java new file mode 100644 index 000000000000..f963dfa98ca5 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java @@ -0,0 +1,56 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Used to configure injection of Plexus components by + * + * MavenPluginManager.getConfiguredMojo(...). + * + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER } ) +@Inherited +public @interface Component +{ + /** + * role of the component to inject. + * @return the role + */ + Class role() default Object.class; + + /** + * hint of the component to inject. + * @return the hint + */ + String hint() default ""; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java new file mode 100644 index 000000000000..e4f870786a26 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java @@ -0,0 +1,64 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Used if your Mojo needs to fork a lifecycle. + * + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Execute +{ + /** + * lifecycle phase to fork. Note that specifying a phase overrides specifying a goal. + * @return the phase + */ + LifecyclePhase phase() default LifecyclePhase.NONE; + + /** + * goal to fork. Note that specifying a phase overrides specifying a goal. The specified goal must be + * another goal of the same plugin. + * @return the goal + */ + String goal() default ""; + + /** + * lifecycle id of the lifecycle that defines {@link #phase()}. Only valid in combination with {@link #phase()}. If + * not specified, Maven will use the lifecycle of the current build. + * + * @see Lifecycle Mappings + * @return the lifecycle id + */ + String lifecycle() default ""; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java new file mode 100644 index 000000000000..c5cfc75ec64e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java @@ -0,0 +1,48 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * Component instantiation strategy. + * + * @since 4.0 + */ +@Experimental +public enum InstantiationStrategy +{ + PER_LOOKUP( "per-lookup" ), + SINGLETON( "singleton" ), + KEEP_ALIVE( "keep-alive" ), + POOLABLE( "poolable" ); + + private final String id; + + InstantiationStrategy( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java new file mode 100644 index 000000000000..84c567b4dcdf --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java @@ -0,0 +1,80 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * Lifecycle phases. + * + * @since 4.0 + */ +@Experimental +public enum LifecyclePhase +{ + + VALIDATE( "validate" ), + INITIALIZE( "initialize" ), + GENERATE_SOURCES( "generate-sources" ), + PROCESS_SOURCES( "process-sources" ), + GENERATE_RESOURCES( "generate-resources" ), + PROCESS_RESOURCES( "process-resources" ), + COMPILE( "compile" ), + PROCESS_CLASSES( "process-classes" ), + GENERATE_TEST_SOURCES( "generate-test-sources" ), + PROCESS_TEST_SOURCES( "process-test-sources" ), + GENERATE_TEST_RESOURCES( "generate-test-resources" ), + PROCESS_TEST_RESOURCES( "process-test-resources" ), + TEST_COMPILE( "test-compile" ), + PROCESS_TEST_CLASSES( "process-test-classes" ), + TEST( "test" ), + PREPARE_PACKAGE( "prepare-package" ), + PACKAGE( "package" ), + PRE_INTEGRATION_TEST( "pre-integration-test" ), + INTEGRATION_TEST( "integration-test" ), + POST_INTEGRATION_TEST( "post-integration-test" ), + VERIFY( "verify" ), + INSTALL( "install" ), + DEPLOY( "deploy" ), + + PRE_CLEAN( "pre-clean" ), + CLEAN( "clean" ), + POST_CLEAN( "post-clean" ), + + PRE_SITE( "pre-site" ), + SITE( "site" ), + POST_SITE( "post-site" ), + SITE_DEPLOY( "site-deploy" ), + + NONE( "" ); + + private final String id; + + LifecyclePhase( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java new file mode 100644 index 000000000000..e87341140d1c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -0,0 +1,98 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.maven.api.ResolutionScope; +import org.apache.maven.api.annotations.Experimental; + +/** + * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin). + * + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Mojo +{ + /** + * goal name (required). + * @return the goal name + */ + String name(); + + /** + * default phase to bind your mojo. + * @return the default phase + */ + LifecyclePhase defaultPhase() default LifecyclePhase.NONE; + + /** + * the required dependency resolution scope. + * @return the required dependency resolution scope + */ + ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE; + + /** + * the required dependency collection scope. + * @return the required dependency collection scope + */ + ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE; + + /** + * your Mojo instantiation strategy. (Only per-lookup and singleton are supported) + * @return the instantiation strategy + */ + InstantiationStrategy instantiationStrategy() default InstantiationStrategy.PER_LOOKUP; + + /** + * does your mojo requires a project to be executed? + * @return requires a project + */ + boolean requiresProject() default true; + + /** + * if the Mojo uses the Maven project and its child modules. + * @return uses the Maven project and its child modules + */ + boolean aggregator() default false; + + /** + * does this Mojo need to be online to be executed? + * @return need to be online + */ + boolean requiresOnline() default false; + + /** + * configurator bean name. + * @return the configurator bean name + */ + String configurator() default ""; + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java new file mode 100644 index 000000000000..27ada3d2a6b2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java @@ -0,0 +1,94 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.apache.maven.api.annotations.Experimental; + +/** + * Used to configure your Mojo parameters to be injected by + * + * MavenPluginManager.getConfiguredMojo(...). + *

+ * Beans injected into Mojo parameters are prepared by Sisu JSR330-based + * container: this annotation is only effective on fields of the Mojo class itself, nested bean injection + * requires Sisu or JSR330 annotations. + * + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD, ElementType.METHOD } ) +@Inherited +public @interface Parameter +{ + /** + * name of the bean property used to get/set the field: by default, field name is used. + * @return the name of the bean property + */ + String name() default ""; + + /** + * alias supported to get parameter value. + * @return the alias + */ + String alias() default ""; + + /** + * Property to use to retrieve a value. Can come from -D execution, setting properties or pom + * properties. + * @return property name + */ + String property() default ""; + + /** + * parameter default value, may contain ${...} expressions which will be interpreted at + * inject time: see + * + * PluginParameterExpressionEvaluator. + * @return the default value + */ + String defaultValue() default ""; + + /** + * is the parameter required? + * @return true if the Mojo should fail when the parameter cannot be injected + */ + boolean required() default false; + + /** + * Specifies that this parameter cannot be configured directly by the user (as in the case of POM-specified + * configuration). This is useful when you want to force the user to use common POM elements rather than plugin + * configurations, as in the case where you want to use the artifact's final name as a parameter. In this case, you + * want the user to modify <build><finalName/></build> rather than specifying a value + * for finalName directly in the plugin configuration section. It is also useful to ensure that - for example - a + * List-typed parameter which expects items of type Artifact doesn't get a List full of Strings. + * + * @return true if the user should not be allowed to configure the parameter directly + */ + boolean readonly() default false; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java new file mode 100644 index 000000000000..a1da37134d91 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java @@ -0,0 +1,71 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service used to create {@link ArtifactCoordinate} objects. + * + * @since 4.0 + */ +@Experimental +public interface ArtifactCoordinateFactory extends Service +{ + + /** + * Creates a coordinate. + * + * @param request the request holding coordinate creation parameters + * @return an {@code Artifact}, never {@code null} + * @throws IllegalArgumentException if {@code request} is null or {@code request.session} is null or invalid + */ + @Nonnull + ArtifactCoordinate create( @Nonnull ArtifactCoordinateFactoryRequest request ); + + @Nonnull + default ArtifactCoordinate create( @Nonnull Session session, String groupId, + String artifactId, String version, String extension ) + { + return create( ArtifactCoordinateFactoryRequest.build( session, groupId, artifactId, version, extension ) ); + } + + @Nonnull + default ArtifactCoordinate create( @Nonnull Session session, String groupId, String artifactId, String version, + String classifier, String extension, String type ) + { + return create( ArtifactCoordinateFactoryRequest.build( session, groupId, artifactId, + version, classifier, extension, type ) ); + } + + @Nonnull + default ArtifactCoordinate create( @Nonnull Session session, Artifact artifact ) + { + return create( ArtifactCoordinateFactoryRequest.build( session, + artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(), + artifact.getClassifier(), artifact.getExtension(), null ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactoryRequest.java new file mode 100644 index 000000000000..8c8b9af06fb0 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactoryRequest.java @@ -0,0 +1,222 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * A request for creating a {@link ArtifactCoordinate} object. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ArtifactCoordinateFactoryRequest +{ + + @Nonnull + Session getSession(); + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + String getClassifier(); + + String getExtension(); + + String getType(); + + static ArtifactCoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String extension ) + { + return ArtifactCoordinateFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .extension( extension ) + .build(); + } + + static ArtifactCoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) + { + return ArtifactCoordinateFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .classifier( classifier ) + .extension( extension ) + .type( type ) + .build(); + } + + static ArtifactCoordinateFactoryRequest build( Session session, ArtifactCoordinate coordinate ) + { + return ArtifactCoordinateFactoryRequest.builder() + .session( session ) + .groupId( coordinate.getGroupId() ) + .artifactId( coordinate.getArtifactId() ) + .classifier( coordinate.getClassifier() ) + .version( coordinate.getVersion().asString() ) + .extension( coordinate.getExtension() ) + .build(); + } + + + static ArtifactFactoryRequestBuilder builder() + { + return new ArtifactFactoryRequestBuilder(); + } + + @NotThreadSafe + class ArtifactFactoryRequestBuilder + { + private Session session; + private String groupId; + private String artifactId; + private String version; + private String classifier; + private String extension; + private String type; + + public ArtifactFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ArtifactFactoryRequestBuilder groupId( String groupId ) + { + this.groupId = groupId; + return this; + } + + public ArtifactFactoryRequestBuilder artifactId( String artifactId ) + { + this.artifactId = artifactId; + return this; + } + + public ArtifactFactoryRequestBuilder version( String version ) + { + this.version = version; + return this; + } + + public ArtifactFactoryRequestBuilder classifier( String classifier ) + { + this.classifier = classifier; + return this; + } + + public ArtifactFactoryRequestBuilder extension( String extension ) + { + this.extension = extension; + return this; + } + + public ArtifactFactoryRequestBuilder type( String type ) + { + this.type = type; + return this; + } + + public ArtifactCoordinateFactoryRequest build() + { + return new DefaultArtifactFactoryRequestArtifact( session, groupId, artifactId, version, + classifier, extension, type ); + } + + private static class DefaultArtifactFactoryRequestArtifact extends BaseRequest implements + ArtifactCoordinateFactoryRequest + { + private final String groupId; + private final String artifactId; + private final String version; + private final String classifier; + private final String extension; + private final String type; + + DefaultArtifactFactoryRequestArtifact( @Nonnull Session session, + String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type ) + { + super( session ); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.classifier = classifier; + this.extension = extension; + this.type = type; + } + + @Override + public String getGroupId() + { + return groupId; + } + + @Override + public String getArtifactId() + { + return artifactId; + } + + @Override + public String getVersion() + { + return version; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getType() + { + return type; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java new file mode 100644 index 000000000000..38c243dbea95 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.Collection; + +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Deploys {@link Artifact}s to a {@link RemoteRepository}. + * + * @since 4.0 + * @see Session#deployArtifact(RemoteRepository, Artifact...) + */ +@Experimental +public interface ArtifactDeployer extends Service +{ + + /** + * @param request {@link ArtifactDeployerRequest} + * @throws ArtifactDeployerException if the deployment failed + */ + void deploy( @Nonnull ArtifactDeployerRequest request ); + + /** + * @param session the repository session + * @param repository the repository to deploy to + * @param artifacts the collection of artifacts to deploy + * @throws ArtifactDeployerException if the deployment failed + * @throws IllegalArgumentException if an argument is {@code null} or invalid + */ + default void deploy( @Nonnull Session session, + @Nonnull RemoteRepository repository, + @Nonnull Collection artifacts ) + { + deploy( ArtifactDeployerRequest.build( session, repository, artifacts ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java new file mode 100644 index 000000000000..fbb206a53489 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java @@ -0,0 +1,48 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * An artifact could not correctly being deployed. + * + * @since 4.0 + */ +@Experimental +public class ArtifactDeployerException + extends MavenException +{ + + /** + * + */ + private static final long serialVersionUID = 7421964724059077698L; + + /** + * @param message The message of the error. + * @param e {@link Exception} + */ + public ArtifactDeployerException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java new file mode 100644 index 000000000000..a87c0fbfc957 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java @@ -0,0 +1,153 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Collection; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.RemoteRepository; + +import static org.apache.maven.api.services.BaseRequest.nonNull; + +/** + * A request for deploying one or more artifacts to a remote repository. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ArtifactDeployerRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + RemoteRepository getRepository(); + + @Nonnull + Collection getArtifacts(); + + int getRetryFailedDeploymentCount(); + + @Nonnull + static ArtifactDeployerRequestBuilder builder() + { + return new ArtifactDeployerRequestBuilder(); + } + + @Nonnull + static ArtifactDeployerRequest build( @Nonnull Session session, + @Nonnull RemoteRepository repository, + @Nonnull Collection artifacts ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .repository( repository ) + .artifacts( artifacts ) + .build(); + } + + class ArtifactDeployerRequestBuilder + { + Session session; + RemoteRepository repository; + Collection artifacts; + int retryFailedDeploymentCount; + + @Nonnull + public ArtifactDeployerRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + @Nonnull + public ArtifactDeployerRequestBuilder repository( RemoteRepository repository ) + { + this.repository = repository; + return this; + } + + public ArtifactDeployerRequestBuilder artifacts( Collection artifacts ) + { + this.artifacts = artifacts; + return this; + } + + public ArtifactDeployerRequestBuilder retryFailedDeploymentCount( int retryFailedDeploymentCount ) + { + this.retryFailedDeploymentCount = retryFailedDeploymentCount; + return this; + } + + @Nonnull + public ArtifactDeployerRequest build() + { + return new DefaultArtifactDeployerRequest( session, repository, artifacts, retryFailedDeploymentCount ); + } + + private static class DefaultArtifactDeployerRequest extends BaseRequest + implements ArtifactDeployerRequest + { + + private final RemoteRepository repository; + private final Collection artifacts; + private final int retryFailedDeploymentCount; + + DefaultArtifactDeployerRequest( @Nonnull Session session, + @Nonnull RemoteRepository repository, + @Nonnull Collection artifacts, + int retryFailedDeploymentCount ) + { + super( session ); + this.repository = nonNull( repository, "repository can not be null" ); + this.artifacts = nonNull( artifacts, "artifacts can not be null" ); + this.retryFailedDeploymentCount = retryFailedDeploymentCount; + } + + @Nonnull + @Override + public RemoteRepository getRepository() + { + return repository; + } + + @Nonnull + @Override + public Collection getArtifacts() + { + return artifacts; + } + + @Override + public int getRetryFailedDeploymentCount() + { + return retryFailedDeploymentCount; + } + } + + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java new file mode 100644 index 000000000000..c9f2095aa069 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service used to create {@link Artifact} objects. + * + * @since 4.0 + */ +@Experimental +public interface ArtifactFactory extends Service +{ + + /** + * Creates an artifact. + * + * @param request the request holding artifact creation parameters + * @return an {@code Artifact}, never {@code null} + * @throws IllegalArgumentException if {@code request} is null or {@code request.session} is null or invalid + */ + @Nonnull + Artifact create( @Nonnull ArtifactFactoryRequest request ); + + @Nonnull + default Artifact create( @Nonnull Session session, String groupId, + String artifactId, String version, String extension ) + { + return create( ArtifactFactoryRequest.build( session, groupId, artifactId, version, extension ) ); + } + + @Nonnull + default Artifact create( @Nonnull Session session, String groupId, String artifactId, String version, + String classifier, String extension, String type ) + { + return create( ArtifactFactoryRequest.build( session, groupId, artifactId, + version, classifier, extension, type ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java new file mode 100644 index 000000000000..eb7e3f96cc91 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java @@ -0,0 +1,208 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ArtifactFactoryRequest +{ + + @Nonnull + Session getSession(); + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + String getClassifier(); + + String getExtension(); + + String getType(); + + static ArtifactFactoryRequest build( Session session, String groupId, String artifactId, + String version, String extension ) + { + return ArtifactFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .extension( extension ) + .build(); + } + + static ArtifactFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) + { + return ArtifactFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .classifier( classifier ) + .extension( extension ) + .type( type ) + .build(); + } + + static ArtifactFactoryRequestBuilder builder() + { + return new ArtifactFactoryRequestBuilder(); + } + + @NotThreadSafe + class ArtifactFactoryRequestBuilder + { + private Session session; + private String groupId; + private String artifactId; + private String version; + private String classifier; + private String extension; + private String type; + + public ArtifactFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ArtifactFactoryRequestBuilder groupId( String groupId ) + { + this.groupId = groupId; + return this; + } + + public ArtifactFactoryRequestBuilder artifactId( String artifactId ) + { + this.artifactId = artifactId; + return this; + } + + public ArtifactFactoryRequestBuilder version( String version ) + { + this.version = version; + return this; + } + + public ArtifactFactoryRequestBuilder classifier( String classifier ) + { + this.classifier = classifier; + return this; + } + + public ArtifactFactoryRequestBuilder extension( String extension ) + { + this.extension = extension; + return this; + } + + public ArtifactFactoryRequestBuilder type( String type ) + { + this.type = type; + return this; + } + + public ArtifactFactoryRequest build() + { + return new DefaultArtifactFactoryRequest( session, groupId, artifactId, version, + classifier, extension, type ); + } + + private static class DefaultArtifactFactoryRequest extends BaseRequest implements ArtifactFactoryRequest + { + private final String groupId; + private final String artifactId; + private final String version; + private final String classifier; + private final String extension; + private final String type; + + DefaultArtifactFactoryRequest( @Nonnull Session session, + String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type ) + { + super( session ); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.classifier = classifier; + this.extension = extension; + this.type = type; + } + + @Override + public String getGroupId() + { + return groupId; + } + + @Override + public String getArtifactId() + { + return artifactId; + } + + @Override + public String getVersion() + { + return version; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getType() + { + return type; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java new file mode 100644 index 000000000000..5b07a88f8420 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java @@ -0,0 +1,74 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; + +/** + * Installs {@link Artifact}s to the local repository. + * + * @since 4.0 + * @see Session#withLocalRepository(org.apache.maven.api.LocalRepository) + */ +@Experimental +public interface ArtifactInstaller extends Service +{ + /** + * @param request {@link ArtifactInstallerRequest} + * @throws ArtifactInstallerException in case of an error. + * @throws IllegalArgumentException in case {@code request} is {@code null}. + */ + void install( ArtifactInstallerRequest request ); + + /** + * @param session the repository session + * @param artifact the {@link Artifact} to install + * @throws ArtifactInstallerException In case of an error which can be the a given artifact can not be found or the + * installation has failed. + * @throws IllegalArgumentException in case of parameter {@code session} is {@code null} or + * {@code artifact} is {@code null}. + */ + default void install( Session session, Artifact artifact ) + { + install( session, Collections.singletonList( artifact ) ); + } + + /** + * @param session the repository session + * @param artifacts Collection of {@link Artifact MavenArtifacts} + * @throws ArtifactInstallerException In case of an error which can be the a given artifact can not be found or the + * installation has failed. + * @throws IllegalArgumentException in case of parameter {@code request} is {@code null} or parameter + * {@code localRepository} is {@code null} or {@code localRepository} is not a directory + * or parameter {@code mavenArtifacts} is {@code null} or + * {@code mavenArtifacts.isEmpty()} is {@code true}. + */ + default void install( Session session, Collection artifacts ) + { + install( ArtifactInstallerRequest.build( session, artifacts ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java new file mode 100644 index 000000000000..e6c6dc6abd81 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java @@ -0,0 +1,46 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * @since 4.0 + */ +@Experimental +public class ArtifactInstallerException + extends MavenException +{ + + /** + * + */ + private static final long serialVersionUID = 3652561971360586373L; + + /** + * @param message The message of the error. + * @param e {@link Exception} + */ + public ArtifactInstallerException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java new file mode 100644 index 000000000000..772203a85801 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java @@ -0,0 +1,113 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; +import org.apache.maven.api.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * A request for installing one or more artifacts in the local repository. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ArtifactInstallerRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + Collection getArtifacts(); + + @Nonnull + static ArtifactInstallerRequestBuilder builder() + { + return new ArtifactInstallerRequestBuilder(); + } + + @Nonnull + static ArtifactInstallerRequest build( Session session, Collection artifacts ) + { + return builder() + .session( session ) + .artifacts( artifacts ) + .build(); + } + + @NotThreadSafe + class ArtifactInstallerRequestBuilder + { + Session session; + Collection artifacts = Collections.emptyList(); + + @Nonnull + public ArtifactInstallerRequestBuilder session( @Nonnull Session session ) + { + this.session = session; + return this; + } + + @Nonnull + public ArtifactInstallerRequestBuilder artifacts( @Nullable Collection artifacts ) + { + this.artifacts = artifacts != null ? artifacts : Collections.emptyList(); + return this; + } + + @Nonnull + public ArtifactInstallerRequest build() + { + return new DefaultArtifactInstallerRequest( session, artifacts ); + } + + static class DefaultArtifactInstallerRequest extends BaseRequest + implements ArtifactInstallerRequest + { + + private final Collection artifacts; + + DefaultArtifactInstallerRequest( @Nonnull Session session, + @Nonnull Collection artifacts ) + { + super( session ); + this.artifacts = nonNull( artifacts, "artifacts can not be null" ); + } + + @Nonnull + @Override + public Collection getArtifacts() + { + return artifacts; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java new file mode 100644 index 000000000000..4fa771343131 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -0,0 +1,64 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Optional; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Metadata; + +/** + * + * @since 4.0 + */ +@Experimental +public interface ArtifactManager extends Service +{ + + /** + * Returns the path of the file previously associated to this artifact + * or {@code Optional.empty()} if no path has been associated. + */ + @Nonnull + Optional getPath( @Nonnull Artifact artifact ); + + /** + * Associates the given file path to the artifact. + */ + void setPath( @Nonnull Artifact artifact, Path path ); + + /** + * TODO: investigate removing the Metadata api completely + */ + @Nonnull + Collection getAttachedMetadatas( @Nonnull Artifact artifact ); + + /** + * TODO: investigate removing the Metadata api completely + */ + void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metadata ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java new file mode 100644 index 000000000000..99f49d241d2b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.Collection; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; + +/** + * Resolves the artifact, i.e download the file when required and attach it to the artifact + * + * @since 4.0 + */ +@Experimental +public interface ArtifactResolver extends Service +{ + + /** + * @param request {@link ArtifactResolverRequest} + * @return {@link ArtifactResolverResult} + * @throws ArtifactResolverException in case of an error. + * @throws IllegalArgumentException in case of parameter {@code buildingRequest} is {@code null} or + * parameter {@code mavenArtifact} is {@code null} or invalid. + */ + ArtifactResolverResult resolve( ArtifactResolverRequest request ); + + /** + * @param session {@link Session} + * @param coordinates array of {@link ArtifactCoordinate} + * @return {@link ArtifactResolverResult} + * @throws ArtifactResolverException in case of an error. + * @throws IllegalArgumentException in case of parameter {@code buildingRequest} is {@code null} or + * parameter {@code coordinate} is {@code null} or invalid. + */ + default ArtifactResolverResult resolve( Session session, + Collection coordinates ) + { + return resolve( ArtifactResolverRequest.build( session, coordinates ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java new file mode 100644 index 000000000000..ba6e5482cf34 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java @@ -0,0 +1,45 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * + * + * @since 4.0 + */ +@Experimental +public class ArtifactResolverException + extends MavenException +{ + + private static final long serialVersionUID = 7252294837746943917L; + + /** + * @param message The message for the exception. + * @param e The exception itself. + */ + public ArtifactResolverException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java new file mode 100644 index 000000000000..f35f326f1453 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -0,0 +1,108 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.Collection; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * A request for resolving an artifact. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ArtifactResolverRequest +{ + @Nonnull + Session getSession(); + + @Nonnull + Collection getCoordinates(); + + @Nonnull + static ArtifactResolverRequestBuilder builder() + { + return new ArtifactResolverRequestBuilder(); + } + + @Nonnull + static ArtifactResolverRequest build( Session session, Collection coordinates ) + { + return builder() + .session( session ) + .coordinates( coordinates ) + .build(); + } + + @NotThreadSafe + class ArtifactResolverRequestBuilder + { + Session session; + Collection coordinates; + + @Nonnull + public ArtifactResolverRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + @Nonnull + public ArtifactResolverRequestBuilder coordinates( Collection coordinates ) + { + this.coordinates = coordinates; + return this; + } + + @Nonnull + public ArtifactResolverRequest build() + { + return new DefaultArtifactResolverRequest( session, coordinates ); + } + + private static class DefaultArtifactResolverRequest extends BaseRequest implements ArtifactResolverRequest + { + @Nonnull + private final Collection coordinates; + + DefaultArtifactResolverRequest( @Nonnull Session session, + @Nonnull Collection coordinates ) + { + super( session ); + this.coordinates = nonNull( coordinates, "coordinates can not be null" ); + } + + @Nonnull + @Override + public Collection getCoordinates() + { + return coordinates; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java new file mode 100644 index 000000000000..74bd5a74116f --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java @@ -0,0 +1,43 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.util.Map; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * The Artifact Result + * + * @since 4.0 + */ +@Experimental +public interface ArtifactResolverResult +{ + /** + * @return {@link Artifact} + */ + @Nonnull + Map getArtifacts(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java new file mode 100644 index 000000000000..86afa5a20d38 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java @@ -0,0 +1,67 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Session; + +/** + * Base class for requests. + * + * @since 4.0 + */ +@Experimental +abstract class BaseRequest +{ + + private final Session session; + + protected BaseRequest( @Nonnull Session session ) + { + this.session = nonNull( session, "session can not be null" ); + } + + @Nonnull + public Session getSession() + { + return session; + } + + public static T nonNull( T obj, String message ) + { + if ( obj == null ) + { + throw new IllegalArgumentException( message ); + } + return obj; + } + + protected static Collection unmodifiable( Collection obj ) + { + return obj != null && !obj.isEmpty() + ? Collections.unmodifiableCollection( new ArrayList<>( obj ) ) : Collections.emptyList(); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java new file mode 100644 index 000000000000..e21b2c46925d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -0,0 +1,117 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Project; + +/** + * The DependencyCollector service can be used to collect dependencies + * for a given artifact and builds a graph of them. + * The dependencies collection mechanism will not download any artifacts, + * and only the pom files will be downloaded. + * + * @since 4.0 + */ +@Experimental +public interface DependencyCollector extends Service +{ + + /** + * Collects the transitive dependencies and builds a dependency graph. + * Note that this operation is only concerned about determining the coordinates of the + * transitive dependencies and does not actually resolve the artifact files. + * + * @param request The dependency collection request, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid + * + * @see DependencyCollector#collect(Session, Project) + * @see DependencyCollector#collect(Session, DependencyCoordinate) + * @see DependencyCollector#collect(Session, Artifact) + */ + @Nonnull + DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ); + + /** + * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the + * artifact files. + * + * @param session The {@link Session}, must not be {@code null}. + * @param root The Maven Dependency, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid + * @see #collect(DependencyCollectorRequest) + */ + @Nonnull + default DependencyCollectorResult collect( @Nonnull Session session, + @Nonnull DependencyCoordinate root ) + { + return collect( DependencyCollectorRequest.build( session, root ) ); + } + + /** + * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the + * artifact files. + * + * @param session The {@link Session}, must not be {@code null}. + * @param project The {@link Project}, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid + * @see #collect(DependencyCollectorRequest) + */ + @Nonnull + default DependencyCollectorResult collect( @Nonnull Session session, + @Nonnull Project project ) + { + return collect( DependencyCollectorRequest.build( session, project ) ); + } + + /** + * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the + * artifact files. + * + * @param session The {@link Session}, must not be {@code null}. + * @param artifact The {@link Artifact}, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid + * @see #collect(DependencyCollectorRequest) + */ + @Nonnull + default DependencyCollectorResult collect( @Nonnull Session session, + @Nonnull Artifact artifact ) + { + return collect( DependencyCollectorRequest.build( session, artifact ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java new file mode 100644 index 000000000000..019fedb6b31b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * Thrown in case of bad artifact descriptors, version ranges or other + * issues encountered during calculation of the dependency graph. + * + * @since 4.0 + */ +@Experimental +public class DependencyCollectorException + extends MavenException +{ + /** + * + */ + private static final long serialVersionUID = -3134726259840210686L; + + /** + * @param message The message you would give for the exception. + * @param cause The cause which is related to the message. + */ + public DependencyCollectorException( String message, Throwable cause ) + { + super( message, cause ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java new file mode 100644 index 000000000000..b0963205d6e5 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -0,0 +1,331 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; +import org.apache.maven.api.annotations.Nullable; + +import static org.apache.maven.api.services.BaseRequest.nonNull; + +/** + * A request to collect the transitive dependencies and to build a dependency graph from them. There are three ways to + * create a dependency graph. First, only the root dependency can be given. Second, a root dependency and direct + * dependencies can be specified in which case the specified direct dependencies are merged with the direct dependencies + * retrieved from the artifact descriptor of the root dependency. And last, only direct dependencies can be specified in + * which case the root node of the resulting graph has no associated dependency. + * + * @since 4.0 + * @see DependencyCollector#collect(DependencyCollectorRequest) + */ +@Experimental +@Immutable +public interface DependencyCollectorRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + Optional getRootArtifact(); + + @Nonnull + Optional getRoot(); + + @Nonnull + Collection getDependencies(); + + @Nonnull + Collection getManagedDependencies(); + + boolean getVerbose(); + + @Nonnull + static DependencyCollectorRequest build( @Nonnull Session session, Artifact root ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .rootArtifact( nonNull( root, "root can not be null" ) ) + .build(); + } + + @Nonnull + static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull DependencyCoordinate root ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .root( nonNull( root, "root can not be null" ) ) + .build(); + } + + @Nonnull + static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull Project project ) + { + nonNull( session, "session can not be null" ); + nonNull( project, "project can not be null" ); + return builder() + .session( session ) + .rootArtifact( project.getArtifact() ) + .dependencies( project.getDependencies() ) + .managedDependencies( project.getManagedDependencies() ) + .build(); + } + + @Nonnull + static DependencyCollectorRequestBuilder builder() + { + return new DependencyCollectorRequestBuilder(); + } + + @NotThreadSafe + class DependencyCollectorRequestBuilder + { + + Session session; + Artifact rootArtifact; + DependencyCoordinate root; + List dependencies = Collections.emptyList(); + List managedDependencies = Collections.emptyList(); + boolean verbose; + + @Nonnull + public DependencyCollectorRequestBuilder session( @Nonnull Session session ) + { + this.session = session; + return this; + } + + /** + * Sets the root artifact for the dependency graph. + * This must not be confused with {@link #root(DependencyCoordinate)}: The root dependency, like any + * other specified dependency, will be subject to dependency collection/resolution, i.e. should have an artifact + * descriptor and a corresponding artifact file. The root artifact on the other hand is only used + * as a label for the root node of the graph in case no root dependency was specified. As such, the configured + * root artifact is ignored if {@link #root(DependencyCoordinate)} has been set. + * + * @param rootArtifact The root artifact for the dependency graph, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder rootArtifact( @Nullable Artifact rootArtifact ) + { + this.rootArtifact = rootArtifact; + return this; + } + + /** + * @param root The root dependency + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder root( @Nonnull DependencyCoordinate root ) + { + this.root = root; + return this; + } + + /** + * Sets the direct dependencies. If both a root dependency and direct dependencies are given in the request, the + * direct dependencies from the request will be merged with the direct dependencies from the root dependency's + * artifact descriptor, giving higher priority to the dependencies from the request. + * + * @param dependencies The direct dependencies, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder dependencies( @Nullable List dependencies ) + { + this.dependencies = ( dependencies != null ) ? dependencies : Collections.emptyList(); + return this; + } + + /** + * Adds the specified direct dependency. + * + * @param dependency The dependency to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder dependency( @Nullable DependencyCoordinate dependency ) + { + if ( dependency != null ) + { + if ( this.dependencies.isEmpty() ) + { + this.dependencies = new ArrayList<>(); + } + this.dependencies.add( dependency ); + } + return this; + } + + + /** + * Sets the dependency management to apply to transitive dependencies. To clarify, this management does not + * apply to + * the direct dependencies of the root node. + * + * @param managedDependencies The dependency management, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder managedDependencies( + @Nullable List managedDependencies ) + { + this.managedDependencies = ( managedDependencies != null ) ? managedDependencies : Collections.emptyList(); + return this; + } + + /** + * Adds the specified managed dependency. + * + * @param managedDependency The managed dependency to add, may be {@code null} in which case the call + * will have no effect. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder managedDependency( @Nullable DependencyCoordinate managedDependency ) + { + if ( managedDependency != null ) + { + if ( this.managedDependencies.isEmpty() ) + { + this.managedDependencies = new ArrayList<>(); + } + this.managedDependencies.add( managedDependency ); + } + return this; + } + + /** + * Specifies that the collection should be verbose. + * + * @param verbose whether the collection should be verbose or not. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder verbose( boolean verbose ) + { + this.verbose = verbose; + return this; + } + + @Nonnull + public DependencyCollectorRequest build() + { + return new DefaultDependencyCollectorRequest( + session, + rootArtifact, + root, + dependencies, + managedDependencies, + verbose ); + } + + static class DefaultDependencyCollectorRequest extends BaseRequest + implements DependencyCollectorRequest + { + private final Artifact rootArtifact; + private final DependencyCoordinate root; + private final Collection dependencies; + private final Collection managedDependencies; + private final boolean verbose; + + + /** + * Creates a request with the specified properties. + * + * @param session {@link Session} + * @param rootArtifact The root dependency whose transitive dependencies should be collected, may be {@code + * null}. + */ + DefaultDependencyCollectorRequest( + @Nonnull Session session, + @Nullable Artifact rootArtifact, + @Nullable DependencyCoordinate root, + @Nonnull Collection dependencies, + @Nonnull Collection managedDependencies, + boolean verbose ) + { + super( session ); + this.rootArtifact = rootArtifact; + this.root = root; + this.dependencies = unmodifiable( dependencies ); + this.managedDependencies = unmodifiable( managedDependencies ); + this.verbose = verbose; + } + + @Nonnull + @Override + public Optional getRootArtifact() + { + return Optional.ofNullable( rootArtifact ); + } + + @Nonnull + @Override + public Optional getRoot() + { + return Optional.ofNullable( root ); + } + + @Nonnull + @Override + public Collection getDependencies() + { + return dependencies; + } + + @Nonnull + @Override + public Collection getManagedDependencies() + { + return managedDependencies; + } + + @Override + public boolean getVerbose() + { + return verbose; + } + + @Nonnull + @Override + public String toString() + { + return getRoot() + " -> " + getDependencies(); + } + + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java new file mode 100644 index 000000000000..09388cca7506 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java @@ -0,0 +1,50 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.Node; +import org.apache.maven.api.annotations.Experimental; + +/** + * The result of a dependency collection request. + * + * @since 4.0 + * @see DependencyCollector#collect(DependencyCollectorRequest) + */ +@Experimental +public interface DependencyCollectorResult +{ + /** + * Gets the exceptions that occurred while building the dependency graph. + * + * @return The exceptions that occurred, never {@code null}. + */ + List getExceptions(); + + /** + * Gets the root node of the dependency graph. + * + * @return The root node of the dependency graph or {@code null} if none. + */ + Node getRoot(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java new file mode 100644 index 000000000000..d3c7a6ffd7c3 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java @@ -0,0 +1,89 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.ReportPlugin; + +/** + * + * @since 4.0 + */ +@Experimental +public interface DependencyCoordinateFactory extends Service +{ + + /** + * Creates a new {@link DependencyCoordinate} object from the request. + * + * @param request the request containing the various data + * @return a new {@link DependencyCoordinate} object. + * + * @throws IllegalArgumentException if {@code request} is null or + * if {@code request.getSession()} is null or invalid + */ + @Nonnull + DependencyCoordinate create( @Nonnull DependencyCoordinateFactoryRequest request ); + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, @Nonnull ArtifactCoordinate coordinate ) + { + return create( DependencyCoordinateFactoryRequest.build( session, coordinate ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, @Nonnull org.apache.maven.api.Dependency dependency ) + { + return create( DependencyCoordinateFactoryRequest.build( session, dependency ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, Dependency dependency ) + { + return create( DependencyCoordinateFactoryRequest.build( session, + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), + dependency.getClassifier(), null, dependency.getType() ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, Plugin plugin ) + { + // TODO: hard coded string + return create( DependencyCoordinateFactoryRequest.build( session, + plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(), + null, null, "maven-plugin" ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, ReportPlugin reportPlugin ) + { + // TODO: hard coded string + return create( DependencyCoordinateFactoryRequest.build( session, + reportPlugin.getGroupId(), reportPlugin.getArtifactId(), reportPlugin.getVersion(), + null, null, "maven-plugin" ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java new file mode 100644 index 000000000000..b42853cd5cdf --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java @@ -0,0 +1,292 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface DependencyCoordinateFactoryRequest extends ArtifactCoordinateFactoryRequest +{ + + String getScope(); + + boolean isOptional(); + + @Nonnull + Collection getExclusions(); + + static DependencyCoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) + { + return DependencyCoordinateFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .classifier( classifier ) + .extension( extension ) + .type( type ) + .build(); + } + + static DependencyCoordinateFactoryRequest build( Session session, ArtifactCoordinate coordinate ) + { + return builder() + .session( session ) + .groupId( coordinate.getGroupId() ) + .artifactId( coordinate.getArtifactId() ) + .version( coordinate.getVersion().asString() ) + .classifier( coordinate.getClassifier() ) + .extension( coordinate.getExtension() ) + .build(); + } + + static DependencyCoordinateFactoryRequest build( Session session, Dependency dependency ) + { + return builder() + .session( session ) + .groupId( dependency.getGroupId() ) + .artifactId( dependency.getArtifactId() ) + .version( dependency.getVersion().asString() ) + .classifier( dependency.getClassifier() ) + .extension( dependency.getExtension() ) + .type( dependency.getType().getName() ) + .scope( dependency.getScope().id() ) + .optional( dependency.isOptional() ) + .build(); + } + + static DependencyCoordinateFactoryRequestBuilder builder() + { + return new DependencyCoordinateFactoryRequestBuilder(); + } + + @NotThreadSafe + class DependencyCoordinateFactoryRequestBuilder + { + private Session session; + private String groupId; + private String artifactId; + private String version; + private String classifier; + private String extension; + private String type; + private String scope; + private boolean optional; + private Collection exclusions = Collections.emptyList(); + + public DependencyCoordinateFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder groupId( String groupId ) + { + this.groupId = groupId; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder artifactId( String artifactId ) + { + this.artifactId = artifactId; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder version( String version ) + { + this.version = version; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder classifier( String classifier ) + { + this.classifier = classifier; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder extension( String extension ) + { + this.extension = extension; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder type( String type ) + { + this.type = type; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder scope( String scope ) + { + this.scope = scope; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder optional( boolean optional ) + { + this.optional = optional; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder exclusions( Collection exclusions ) + { + if ( exclusions != null ) + { + if ( this.exclusions.isEmpty() ) + { + this.exclusions = new ArrayList<>(); + } + this.exclusions.addAll( exclusions ); + } + return this; + } + + public DependencyCoordinateFactoryRequestBuilder exclusion( Exclusion exclusion ) + { + if ( exclusion != null ) + { + if ( this.exclusions.isEmpty() ) + { + this.exclusions = new ArrayList<>(); + } + this.exclusions.add( exclusion ); + } + return this; + } + + public DependencyCoordinateFactoryRequest build() + { + return new DefaultDependencyCoordinateFactoryRequest( session, groupId, artifactId, version, + classifier, extension, type, scope, optional, exclusions ); + } + + private static class DefaultDependencyCoordinateFactoryRequest + extends BaseRequest + implements DependencyCoordinateFactoryRequest + { + private final String groupId; + private final String artifactId; + private final String version; + private final String classifier; + private final String extension; + private final String type; + private final String scope; + private final boolean optional; + private final Collection exclusions; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + private DefaultDependencyCoordinateFactoryRequest( + @Nonnull Session session, String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type, + String scope, + boolean optional, + Collection exclusions ) + { + super( session ); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.classifier = classifier; + this.extension = extension; + this.type = type; + this.scope = scope; + this.optional = optional; + this.exclusions = exclusions; + } + + @Override + public String getGroupId() + { + return groupId; + } + + @Override + public String getArtifactId() + { + return artifactId; + } + + @Override + public String getVersion() + { + return version; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getType() + { + return type; + } + + @Override + public String getScope() + { + return scope; + } + + @Override + public boolean isOptional() + { + return optional; + } + + @Nonnull + @Override + public Collection getExclusions() + { + return exclusions; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java new file mode 100644 index 000000000000..5e40ac83fb01 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java @@ -0,0 +1,48 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; + +/** + * + * @since 4.0 + */ +@Experimental +public interface LocalRepositoryManager extends Service +{ + + Path getPathForLocalArtifact( Session session, LocalRepository local, Artifact artifact ); + + Path getPathForLocalMetadata( Session session, LocalRepository local, Metadata metadata ); + + Path getPathForRemoteArtifact( Session session, LocalRepository local, RemoteRepository remote, Artifact artifact ); + + Path getPathForRemoteMetadata( Session session, LocalRepository local, RemoteRepository remote, Metadata metadata ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java new file mode 100644 index 000000000000..93e24994edbb --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java @@ -0,0 +1,38 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.Service; + +public interface Lookup extends Service +{ + + T lookup( Class type ); + + T lookup( Class type, String name ); + + List lookupList( Class type ); + + Map lookupMap( Class type ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java new file mode 100644 index 000000000000..d88549112e87 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java @@ -0,0 +1,50 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class throw by the {@link Lookup} service. + * + * @since 4.0 + */ +@Experimental +public class LookupException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public LookupException( String message, Exception e ) + { + super( message, e ); + } + + /** + * @param e The {@link Exception}. + */ + public LookupException( Exception e ) + { + super( e ); + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java similarity index 52% rename from maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java index 39ffb7ef92f3..aba7dd7219c1 100644 --- a/maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java @@ -1,4 +1,4 @@ -package org.apache.maven.settings; +package org.apache.maven.api.services; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,37 +19,33 @@ * under the License. */ -import java.io.File; +import org.apache.maven.api.annotations.Experimental; /** - * To handle runtime information like local repository or profiles. + * Base class for all maven exceptions. * + * @since 4.0 */ -@Deprecated -public class RuntimeInfo +@Experimental +public class MavenException extends RuntimeException { - @SuppressWarnings( "checkstyle:constantname" ) - public static final String userHome = System.getProperty( "user.home" ); - - @SuppressWarnings( "checkstyle:constantname" ) - public static final File userMavenConfigurationHome = new File( userHome, ".m2" ); - - public static final File DEFAULT_USER_SETTINGS_FILE = new File( userMavenConfigurationHome, "settings.xml" ); - - private File settings; + public MavenException() + { + } - public RuntimeInfo() + public MavenException( String message ) { - this.settings = DEFAULT_USER_SETTINGS_FILE; + super( message ); } - public RuntimeInfo( File settings ) + public MavenException( String message, Throwable cause ) { - this.settings = settings; + super( message, cause ); } - public File getFile() + public MavenException( Throwable cause ) { - return settings; + super( cause ); } + } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java new file mode 100644 index 000000000000..1d86911995b6 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java @@ -0,0 +1,157 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +/** + * Message builder that supports configurable styling. + * + * @since 4.0 + * @see MessageBuilderFactory + */ +public interface MessageBuilder +{ + /** + * Append message content in success style. + * By default, bold green + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder success( Object message ); + + /** + * Append message content in warning style. + * By default, bold yellow + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder warning( Object message ); + + /** + * Append message content in failure style. + * By default, bold red + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder failure( Object message ); + + /** + * Append message content in strong style. + * By default, bold + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder strong( Object message ); + + /** + * Append message content in mojo style. + * By default, green + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder mojo( Object message ); + + /** + * Append message content in project style. + * By default, cyan + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder project( Object message ); + + // + // message building methods modelled after Ansi methods + // + /** + * Append content to the message buffer. + * @param value the content to append + * @param offset the index of the first {@code char} to append + * @param len the number of {@code char}s to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( char[] value, int offset, int len ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( char[] value ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @param start the starting index of the subsequence to be appended + * @param end the end index of the subsequence to be appended + * @return the current builder + */ + @Nonnull + MessageBuilder a( CharSequence value, int start, int end ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( CharSequence value ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( Object value ); + + /** + * Append newline to the message buffer. + * @return the current builder + */ + @Nonnull + MessageBuilder newline(); + + /** + * Append formatted content to the buffer. + * @see String#format(String, Object...) + * @param pattern a format string + * @param args arguments referenced by the format specifiers in the format string. + * @return the current builder + */ + @Nonnull + MessageBuilder format( String pattern, Object... args ); + + /** + * Return the built message. + * @return the message + */ + @Nonnull + String build(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java new file mode 100644 index 000000000000..5290dab1487d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java @@ -0,0 +1,71 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A factory for {@link MessageBuilder}. + * + * @since 4.0 + */ +@Experimental +public interface MessageBuilderFactory extends Service +{ + /** + * Checks if the underlying output does support styling or not. + * @return whether color styling is supported or not + */ + boolean isColorEnabled(); + + /** + * Returns the terminal width or -1 if not supported. + * @return the terminal width + */ + int getTerminalWidth(); + + /** + * Creates a new message builder. + * @return a new message builder + */ + @Nonnull + MessageBuilder builder(); + + /** + * Creates a new message builder backed by the given string builder. + * @param stringBuilder a string builder + * @return a new message builder + */ + @Nonnull + MessageBuilder builder( @Nonnull StringBuilder stringBuilder ); + + /** + * Creates a new message builder of the specified size. + * @param size the initial size of the message builder buffer + * @return a new message builder + */ + @Nonnull + default MessageBuilder builder( int size ) + { + return builder( new StringBuilder( size ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java new file mode 100644 index 000000000000..d7829752f958 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -0,0 +1,110 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * @since 4.0 + */ +@Experimental +public interface ProjectBuilder extends Service +{ + + /** + * Creates a {@link org.apache.maven.api.Project} from a POM file. + * + * @param request {@link ProjectBuilderRequest} + * @return the {@link ProjectBuilderResult} containing the built project and possible errors + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + */ + @Nonnull + ProjectBuilderResult build( ProjectBuilderRequest request ); + + /** + * Creates a {@link org.apache.maven.api.Project} from a POM file. + * + * @param session The {@link Session}, must not be {@code null}. + * @param source The {@link ProjectBuilderSource}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) + { + return build( ProjectBuilderRequest.build( session, source ) ); + } + + /** + * Creates a {@link org.apache.maven.api.Project} from a POM file. + * + * @param session The {@link Session}, must not be {@code null}. + * @param path The {@link Path}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Path path ) + { + return build( ProjectBuilderRequest.build( session, path ) ); + } + + /** + * Creates a {@link org.apache.maven.api.Project} from an artifact. + * + * @param session The {@link Session}, must not be {@code null}. + * @param artifact The {@link Artifact}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Artifact artifact ) + { + return build( ProjectBuilderRequest.build( session, artifact ) ); + } + + /** + * Creates a {@link org.apache.maven.api.Project} from a coordinate. + * + * @param session The {@link Session}, must not be {@code null}. + * @param coordinate The {@link ArtifactCoordinate}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull ArtifactCoordinate coordinate ) + { + return build( ProjectBuilderRequest.build( session, coordinate ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java new file mode 100644 index 000000000000..2256bd144611 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class throw by the {@link ProjectBuilder} service. + * + * @since 4.0 + */ +@Experimental +public class ProjectBuilderException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public ProjectBuilderException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java new file mode 100644 index 000000000000..fef6ceae0dd4 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java @@ -0,0 +1,90 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * Describes a problem that was encountered during project building. A problem can either be an exception that was + * thrown or a simple string message. In addition, a problem carries a hint about its source. + * + * @since 4.0 + */ +@Experimental +public interface ProjectBuilderProblem +{ + + /** + * Gets the hint about the source of the problem. While the syntax of this hint is unspecified and depends on the + * creator of the problem, the general expectation is that the hint provides sufficient information to the user to + * track the problem back to its origin. A concrete example for such a source hint can be the file path or URL from + * which the settings were read. + * + * @return The hint about the source of the problem or an empty string if unknown, never {@code null}. + */ + String getSource(); + + /** + * Gets the one-based index of the line containing the problem. The line number should refer to some text file that + * is given by {@link #getSource()}. + * + * @return The one-based index of the line containing the problem or a non-positive value if unknown. + */ + int getLineNumber(); + + /** + * Gets the one-based index of the column containing the problem. The column number should refer to some text file + * that is given by {@link #getSource()}. + * + * @return The one-based index of the column containing the problem or non-positive value if unknown. + */ + int getColumnNumber(); + + /** + * Gets the location of the problem. The location is a user-friendly combination of the values from + * {@link #getSource()}, {@link #getLineNumber()} and {@link #getColumnNumber()}. The exact syntax of the returned + * value is undefined. + * + * @return The location of the problem, never {@code null}. + */ + String getLocation(); + + /** + * Gets the exception that caused this problem (if any). + * + * @return The exception that caused this problem or {@code null} if not applicable. + */ + Exception getException(); + + /** + * Gets the message that describes this problem. + * + * @return The message describing this problem, never {@code null}. + */ + String getMessage(); + + /** + * Gets the severity level of this problem. + * + * @return The severity level of this problem, never {@code null}. + */ + ProjectBuilderProblemSeverity getSeverity(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java new file mode 100644 index 000000000000..6af0257098fc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The different severity levels for a problem, in decreasing order. + * + * @since 4.0 + */ +@Experimental +public enum ProjectBuilderProblemSeverity +{ + + FATAL, // + ERROR, // + WARNING // + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java new file mode 100644 index 000000000000..4b90e8bfd559 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -0,0 +1,262 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; +import org.apache.maven.api.annotations.Nullable; + +import java.nio.file.Path; +import java.util.Optional; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +import static org.apache.maven.api.services.BaseRequest.nonNull; + +/** + * Request used to build a {@link org.apache.maven.api.Project} using + * the {@link ProjectBuilder} service. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface ProjectBuilderRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + Optional getPath(); + + @Nonnull + Optional getSource(); + + @Nonnull + Optional getArtifact(); + + @Nonnull + Optional getCoordinate(); + + boolean isAllowStubModel(); + + boolean isRecursive(); + + boolean isProcessPlugins(); + + boolean isResolveDependencies(); + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .source( nonNull( source, "source can not be null" ) ) + .build(); + } + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Path path ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .path( nonNull( path, "path can not be null" ) ) + .build(); + } + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Artifact artifact ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .artifact( nonNull( artifact, "artifact can not be null" ) ) + .build(); + } + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ArtifactCoordinate coordinate ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .coordinate( nonNull( coordinate, "coordinate can not be null" ) ) + .build(); + } + + @Nonnull + static ProjectBuilderRequestBuilder builder() + { + return new ProjectBuilderRequestBuilder(); + } + + @NotThreadSafe + class ProjectBuilderRequestBuilder + { + Session session; + Path path; + ProjectBuilderSource source; + Artifact artifact; + ArtifactCoordinate coordinate; + boolean allowStubModel; + boolean recursive; + boolean processPlugins = true; + boolean resolveDependencies = true; + + public ProjectBuilderRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ProjectBuilderRequestBuilder path( Path path ) + { + this.path = path; + return this; + } + + public ProjectBuilderRequestBuilder source( ProjectBuilderSource source ) + { + this.source = source; + return this; + } + + public ProjectBuilderRequestBuilder artifact( Artifact artifact ) + { + this.artifact = artifact; + return this; + } + + public ProjectBuilderRequestBuilder coordinate( ArtifactCoordinate coordinate ) + { + this.coordinate = coordinate; + return this; + } + + public ProjectBuilderRequestBuilder processPlugins( boolean processPlugins ) + { + this.processPlugins = processPlugins; + return this; + } + + public ProjectBuilderRequestBuilder resolveDependencies( boolean resolveDependencies ) + { + this.resolveDependencies = resolveDependencies; + return this; + } + + public ProjectBuilderRequest build() + { + return new DefaultProjectBuilderRequest( session, path, source, artifact, coordinate, + allowStubModel, recursive, processPlugins, resolveDependencies ); + } + + private static class DefaultProjectBuilderRequest extends BaseRequest + implements ProjectBuilderRequest + { + private final Path path; + private final ProjectBuilderSource source; + private final Artifact artifact; + private final ArtifactCoordinate coordinate; + private final boolean allowStubModel; + private final boolean recursive; + private final boolean processPlugins; + private final boolean resolveDependencies; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + DefaultProjectBuilderRequest( @Nonnull Session session, + @Nullable Path path, + @Nullable ProjectBuilderSource source, + @Nullable Artifact artifact, + @Nullable ArtifactCoordinate coordinate, + boolean allowStubModel, + boolean recursive, + boolean processPlugins, + boolean resolveDependencies ) + { + super( session ); + this.path = path; + this.source = source; + this.artifact = artifact; + this.coordinate = coordinate; + this.allowStubModel = allowStubModel; + this.recursive = recursive; + this.processPlugins = processPlugins; + this.resolveDependencies = resolveDependencies; + } + + @Nonnull + @Override + public Optional getPath() + { + return Optional.ofNullable( path ); + } + + @Nonnull + @Override + public Optional getSource() + { + return Optional.ofNullable( source ); + } + + @Nonnull + @Override + public Optional getArtifact() + { + return Optional.ofNullable( artifact ); + } + + @Nonnull + @Override + public Optional getCoordinate() + { + return Optional.ofNullable( coordinate ); + } + + @Override + public boolean isAllowStubModel() + { + return allowStubModel; + } + + @Override + public boolean isRecursive() + { + return recursive; + } + + @Override + public boolean isProcessPlugins() + { + return processPlugins; + } + + @Override + public boolean isResolveDependencies() + { + return resolveDependencies; + } + } + + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java new file mode 100644 index 000000000000..a76b6cab2ffb --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java @@ -0,0 +1,83 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Optional; + +import org.apache.maven.api.Project; + +/** + * Result of a project build call. + * + * @since 4.0 + */ +@Experimental +public interface ProjectBuilderResult +{ + + /** + * Gets the identifier of the project that could not be built. The general format of the identifier is {@code + * ::} but some of these coordinates may still be unknown at the point the exception + * is thrown so this information is merely meant to assist the user. + * + * @return The identifier of the project or an empty string if not known, never {@code null}. + */ + @Nonnull + String getProjectId(); + + /** + * Gets the POM file from which the project was built. + * + * @return The optional POM file. + */ + @Nonnull + Optional getPomFile(); + + /** + * Gets the project that was built. + * + * @return The project that was built or {@code null} if an error occurred and this result accompanies a + * {@link ProjectBuilderException}. + */ + @Nonnull + Optional getProject(); + + /** + * Gets the problems that were encountered during the project building. + * + * @return The problems that were encountered during the project building, can be empty but never {@code null}. + */ + @Nonnull + Collection getProblems(); + + /** + * Gets the result of the dependency resolution for the project. + * + * @return The result of the dependency resolution for the project. + */ + @Nonnull + Optional getDependencyResolverResult(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java new file mode 100644 index 000000000000..1add18cb12fb --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java @@ -0,0 +1,38 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; + +import org.apache.maven.api.annotations.Experimental; + +/** + * The source for a project's XML model. + * + * @since 4.0 + */ +@Experimental +public interface ProjectBuilderSource +{ + InputStream getInputStream() throws IOException; + + String getLocation(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java new file mode 100644 index 000000000000..a908bf19aca9 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -0,0 +1,93 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.ResolutionScope; +import org.apache.maven.api.Session; + +/** + * Interface to manage the project during its lifecycle. + * + * @since 4.0 + */ +@Experimental +public interface ProjectManager extends Service +{ + /** + * Returns the path to the resolved file in the local repository + * if the artifact has been resolved. + * + * @return the path of the resolved artifact + */ + @Nonnull + Optional getPath( Project project ); + + @Nonnull + Collection getAttachedArtifacts( Project project ); + + default void attachArtifact( Session session, Project project, Path path ) + { + String name = path.getFileName().toString(); + int dot = name.lastIndexOf( '.' ); + String ext = dot >= 1 ? name.substring( dot + 1 ) : ""; + Artifact artifact = session.createArtifact( project.getGroupId(), project.getArtifactId(), + project.getVersion(), ext ); + attachArtifact( project, artifact, path ); + } + + default void attachArtifact( Session session, Project project, String type, Path path ) + { + Artifact artifact = session.createArtifact( project.getGroupId(), project.getArtifactId(), + project.getVersion(), null, null, type ); + attachArtifact( project, artifact, path ); + } + + void attachArtifact( Project project, Artifact artifact, Path path ); + + List getCompileSourceRoots( Project project ); + + void addCompileSourceRoot( Project project, String sourceRoot ); + + List getTestCompileSourceRoots( Project project ); + + void addTestCompileSourceRoot( Project project, String sourceRoot ); + + List getRepositories( Project project ); + + List getResolvedDependencies( Project project, ResolutionScope scope ); + + Node getCollectedDependencies( Project project, ResolutionScope scope ); + + void setProperty( Project project, String key, String value ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java new file mode 100644 index 000000000000..a5229f4b4f89 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java @@ -0,0 +1,106 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; + +/** + * Service used to interact with the end user. + * + * @since 4.0 + */ +@Experimental +public interface Prompter extends Service +{ + /** + * Prompts the user for a string. + * + * @param message the message to display to the user + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + default String prompt( String message ) + throws PrompterException + { + return prompt( message, null, null ); + } + + /** + * Prompts the user for a string using a default value. + * + * @param message the message to display + * @param defaultReply the default reply value + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + default String prompt( String message, String defaultReply ) + throws PrompterException + { + return prompt( message, null, defaultReply ); + } + + /** + * Prompts the user for a string using a list of possible values. + * + * @param message the message to display + * @param possibleValues the list of possible values + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + default String prompt( String message, List possibleValues ) + throws PrompterException + { + return prompt( message, possibleValues, null ); + } + + /** + * Prompts the user for a string using a list of possible values and a default reply. + * + * @param message the message to display + * @param possibleValues the list of possible values + * @param defaultReply the default reply value + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + String prompt( String message, List possibleValues, String defaultReply ) + throws PrompterException; + + /** + * Prompts the user for a password. + * + * @param message the message to display + * @return the password entered by the user + * @throws PrompterException if an exception occurs + */ + String promptForPassword( String message ) + throws PrompterException; + + /** + * Displays a message to the user. + * + * @param message the message to display + * @throws PrompterException if an exception occurs + */ + void showMessage( String message ) + throws PrompterException; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java new file mode 100644 index 000000000000..4f892c749412 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class throw by the {@link Prompter} service. + * + * @since 4.0 + */ +@Experimental +public class PrompterException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public PrompterException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java new file mode 100644 index 000000000000..727a3e485f5d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java @@ -0,0 +1,49 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Repository; + +/** + * Factory service to create {@link LocalRepository} or {@link RemoteRepository} objects. + * + * @since 4.0 + */ +@Experimental +public interface RepositoryFactory extends Service +{ + + @Nonnull + LocalRepository createLocal( @Nonnull Path path ); + + @Nonnull + RemoteRepository createRemote( @Nonnull String id, @Nonnull String url ); + + @Nonnull + RemoteRepository createRemote( @Nonnull Repository repository ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java new file mode 100644 index 000000000000..9b0c54d55521 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java @@ -0,0 +1,33 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; + +/** + * @since 4.0 + */ +@Experimental +@Consumer +public interface ToolchainFactory +{ + // TODO: implement ToolchainFactory +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java new file mode 100644 index 000000000000..d5c6c5779de9 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -0,0 +1,82 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.Toolchain; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service to manage {@link Toolchain}s. + * + * @since 4.0 + */ +@Experimental +public interface ToolchainManager extends Service +{ + + /** + * + * @param session + * @param type + * @param requirements + * @return the selected {@link Toolchain}s + * @throws ToolchainManagerException if an exception occurs + */ + @Nonnull + List getToolchains( @Nonnull Session session, String type, Map requirements ); + + /** + * + * @param session + * @param type + * @return the selected {@link Toolchain} + * @throws ToolchainManagerException if an exception occurs + */ + @Nonnull + Optional getToolchainFromBuildContext( @Nonnull Session session, String type ) + throws ToolchainManagerException; + + /** + * + * @param session + * @param type + * @return the selected {@link Toolchain}s + * @throws ToolchainManagerException if an exception occurs + */ + @Nonnull + List getToolchainsForType( @Nonnull Session session, String type ) + throws ToolchainManagerException; + + /** + * + * @param session + * @param toolchain + * @throws ToolchainManagerException if an exception occurs + */ + void storeToolchainToBuildContext( @Nonnull Session session, Toolchain toolchain ) + throws ToolchainManagerException; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java new file mode 100644 index 000000000000..2c8a2bd8fe59 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class throw by the {@link ToolchainManager}. + * + * @since 4.0 + */ +@Experimental +public class ToolchainManagerException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public ToolchainManagerException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java new file mode 100644 index 000000000000..21482ba40ba2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.Type; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Access to {@link Type} registry. + * + * @since 4.0 + */ +@Experimental +public interface TypeRegistry extends Service +{ + + /** + * Obtain the {@link Type} from the specified {@code id}. + * If no type is known for {@code id}, the registry will + * create a custom {@code Type} for it. + * + * @param id the id of the type to retrieve + * @return the type + */ + @Nonnull + Type getType( @Nonnull String id ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java new file mode 100644 index 000000000000..ed5e69ba75c7 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java @@ -0,0 +1,62 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.Version; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service interface to parse {@link Version} and {@link VersionRange}. + * + * @since 4.0 + */ +@Experimental +public interface VersionParser extends Service +{ + /** + * Parses the specified version string, for example "1.0". + * + * @param version The version string to parse, must not be {@code null}. + * @return The parsed version, never {@code null}. + * @throws VersionParserException If the string violates the syntax rules of this scheme. + * @see org.apache.maven.api.Session#parseVersion(String) + */ + @Nonnull + Version parseVersion( @Nonnull String version ); + + /** + * Parses the specified version range specification, for example "[1.0,2.0)". + * + * @param range The range specification to parse, must not be {@code null}. + * @return The parsed version range, never {@code null}. + * @throws VersionParserException If the range specification violates the syntax rules of this scheme. + */ + @Nonnull + VersionRange parseVersionRange( @Nonnull String range ); + + /** + * Checks whether a given artifact version is considered a {@code SNAPSHOT} or not. + */ + boolean isSnapshot( @Nonnull String version ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java new file mode 100644 index 000000000000..f0c4481132e2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class thrown by {@link VersionParser}. + * + * @since 4.0 + */ +@Experimental +public class VersionParserException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public VersionParserException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java new file mode 100644 index 000000000000..8de030ff7080 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java @@ -0,0 +1,34 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.model.Model; + +/** + * Reads or writes a {@link Model} using XML. + * + * @since 4.0 + */ +@Experimental +public interface ModelXmlFactory extends XmlFactory +{ + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java new file mode 100644 index 000000000000..0d6672ae94f5 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java @@ -0,0 +1,34 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.settings.Settings; + +/** + * Reads and writes a {@link Settings} object to/from XML. + * + * @since 4.0 + */ +@Experimental +public interface SettingsXmlFactory extends XmlFactory +{ + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java new file mode 100644 index 000000000000..854cb9791386 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java @@ -0,0 +1,34 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.toolchain.PersistedToolchains; + +/** + * Reads and writes a {@link PersistedToolchains} object to/from XML. + * + * @since 4.0 + */ +@Experimental +public interface ToolchainsXmlFactory extends XmlFactory +{ + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java new file mode 100644 index 000000000000..651b1a5fe8e3 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java @@ -0,0 +1,98 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.nio.file.Path; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.Service; + +/** + * Generic interface to read/write objects to/from XML. + * + * @param the object type to read/write + * @since 4.0 + */ +@Experimental +public interface XmlFactory extends Service +{ + + @Nonnull + default T read( @Nonnull Path path ) throws XmlReaderException + { + return read( path, true ); + } + + @Nonnull + default T read( @Nonnull Path path, boolean strict ) throws XmlReaderException + { + return read( XmlReaderRequest.builder().path( path ).strict( strict ).build() ); + } + + @Nonnull + default T read( @Nonnull InputStream input ) throws XmlReaderException + { + return read( input, true ); + } + + @Nonnull + default T read( @Nonnull InputStream input, boolean strict ) throws XmlReaderException + { + return read( XmlReaderRequest.builder().inputStream( input ).strict( strict ).build() ); + } + + @Nonnull + default T read( @Nonnull Reader reader ) throws XmlReaderException + { + return read( reader, true ); + } + + @Nonnull + default T read( @Nonnull Reader reader, boolean strict ) throws XmlReaderException + { + return read( XmlReaderRequest.builder().reader( reader ).strict( strict ).build() ); + } + + @Nonnull + T read( @Nonnull XmlReaderRequest request ) throws XmlReaderException; + + default void write( @Nonnull T content, @Nonnull Path path ) throws XmlWriterException + { + write( XmlWriterRequest.builder().content( content ).path( path ).build() ); + } + + default void write( @Nonnull T content, @Nonnull OutputStream outputStream ) throws XmlWriterException + { + write( XmlWriterRequest.builder().content( content ).outputStream( outputStream ).build() ); + } + + default void write( @Nonnull T content, @Nonnull Writer writer ) throws XmlWriterException + { + write( XmlWriterRequest.builder().content( content ).writer( writer ).build() ); + } + + void write( @Nonnull XmlWriterRequest request ) throws XmlWriterException; + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java new file mode 100644 index 000000000000..2cc30c0c26cf --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java @@ -0,0 +1,44 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.services.MavenException; + +/** + * An exception thrown during the reading of an xml file. + * + * @since 4.0 + */ +@Experimental +public class XmlReaderException + extends MavenException +{ + + /** + * @param message The message for the exception. + * @param e The exception itself. + */ + public XmlReaderException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java new file mode 100644 index 000000000000..05e4423039bf --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java @@ -0,0 +1,236 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.Reader; +import java.net.URL; +import java.nio.file.Path; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * An XML reader request. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface XmlReaderRequest +{ + + Path getPath(); + + URL getURL(); + + InputStream getInputStream(); + + Reader getReader(); + + Transformer getTransformer(); + + boolean isStrict(); + + String getModelId(); + + String getLocation(); + + boolean isAddDefaultEntities(); + + interface Transformer + { + /** + * Interpolate the value read from the xml document + * + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + + @Nonnull + static XmlReaderRequestBuilder builder() + { + return new XmlReaderRequestBuilder(); + } + + @NotThreadSafe + class XmlReaderRequestBuilder + { + Path path; + URL url; + InputStream inputStream; + Reader reader; + Transformer transformer; + boolean strict; + String modelId; + String location; + boolean addDefaultEntities = true; + + public XmlReaderRequestBuilder path( Path path ) + { + this.path = path; + return this; + } + + public XmlReaderRequestBuilder url( URL url ) + { + this.url = url; + return this; + } + + public XmlReaderRequestBuilder inputStream( InputStream inputStream ) + { + this.inputStream = inputStream; + return this; + } + + public XmlReaderRequestBuilder reader( Reader reader ) + { + this.reader = reader; + return this; + } + + public XmlReaderRequestBuilder transformer( Transformer transformer ) + { + this.transformer = transformer; + return this; + } + + public XmlReaderRequestBuilder strict( boolean strict ) + { + this.strict = strict; + return this; + } + + public XmlReaderRequestBuilder modelId( String modelId ) + { + this.modelId = modelId; + return this; + } + + public XmlReaderRequestBuilder location( String location ) + { + this.location = location; + return this; + } + + public XmlReaderRequestBuilder addDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + return this; + } + + public XmlReaderRequest build() + { + return new DefaultXmlReaderRequest( path, url, inputStream, reader, transformer, strict, + modelId, location, addDefaultEntities ); + } + + private static class DefaultXmlReaderRequest implements XmlReaderRequest + { + final Path path; + final URL url; + final InputStream inputStream; + final Reader reader; + final Transformer transformer; + final boolean strict; + final String modelId; + final String location; + final boolean addDefaultEntities; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + DefaultXmlReaderRequest( Path path, URL url, InputStream inputStream, Reader reader, + Transformer transformer, boolean strict, + String modelId, String location, + boolean addDefaultEntities ) + { + this.path = path; + this.url = url; + this.inputStream = inputStream; + this.reader = reader; + this.transformer = transformer; + this.strict = strict; + this.modelId = modelId; + this.location = location; + this.addDefaultEntities = addDefaultEntities; + } + + @Override + public Path getPath() + { + return path; + } + + @Override + public URL getURL() + { + return null; + } + + @Override + public InputStream getInputStream() + { + return inputStream; + } + + public Reader getReader() + { + return reader; + } + + @Override + public Transformer getTransformer() + { + return transformer; + } + + @Override + public boolean isStrict() + { + return strict; + } + + @Override + public String getModelId() + { + return modelId; + } + + @Override + public String getLocation() + { + return location; + } + + @Override + public boolean isAddDefaultEntities() + { + return addDefaultEntities; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java new file mode 100644 index 000000000000..099b6ea12b19 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java @@ -0,0 +1,44 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.services.MavenException; + +/** + * An exception thrown during the writing of an xml file. + * + * @since 4.0 + */ +@Experimental +public class XmlWriterException + extends MavenException +{ + + /** + * @param message The message for the exception. + * @param e The exception itself. + */ + public XmlWriterException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java new file mode 100644 index 000000000000..15f0319dd81e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java @@ -0,0 +1,127 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import java.io.OutputStream; +import java.io.Writer; +import java.nio.file.Path; + +import org.apache.maven.api.annotations.Experimental; + +/** + * An XML writer request. + * + * @since 4.0 + * @param the object type to read + */ +@Experimental +public interface XmlWriterRequest +{ + + Path getPath(); + + OutputStream getOutputStream(); + + Writer getWriter(); + + T getContent(); + + static XmlWriterRequestBuilder builder() + { + return new XmlWriterRequestBuilder<>(); + } + + class XmlWriterRequestBuilder + { + Path path; + OutputStream outputStream; + Writer writer; + T content; + + public XmlWriterRequestBuilder path( Path path ) + { + this.path = path; + return this; + } + + public XmlWriterRequestBuilder outputStream( OutputStream outputStream ) + { + this.outputStream = outputStream; + return this; + } + + public XmlWriterRequestBuilder writer( Writer writer ) + { + this.writer = writer; + return this; + } + + public XmlWriterRequestBuilder content( T content ) + { + this.content = content; + return this; + } + + public XmlWriterRequest build() + { + return new DefaultXmlWriterRequest<>( path, outputStream, writer, content ); + } + + private static class DefaultXmlWriterRequest implements XmlWriterRequest + { + final Path path; + final OutputStream outputStream; + final Writer writer; + final T content; + + DefaultXmlWriterRequest( Path path, OutputStream outputStream, Writer writer, T content ) + { + this.path = path; + this.outputStream = outputStream; + this.writer = writer; + this.content = content; + } + + @Override + public Path getPath() + { + return path; + } + + @Override + public OutputStream getOutputStream() + { + return outputStream; + } + + @Override + public Writer getWriter() + { + return writer; + } + + @Override + public T getContent() + { + return content; + } + } + } +} diff --git a/api/maven-api-meta/pom.xml b/api/maven-api-meta/pom.xml new file mode 100644 index 000000000000..8c4d392ad268 --- /dev/null +++ b/api/maven-api-meta/pom.xml @@ -0,0 +1,32 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-meta + Maven API Meta annotations + + diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java new file mode 100644 index 000000000000..f8de92bb3a12 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A type implemented by, or extended by maven plugins or extensions. + * Maven plugins or extensions may provide implementations of those types which will be used by maven. + *

+ * A type can be marked {@link Consumer} or {@link Provider} but not both. A type is assumed to be + * {@link Consumer} if it is not marked either {@link Consumer} or {@link Provider}. + *

+ * A package can be marked {@link Provider}. In this case, all types in the package are considered + * to be a provider type regardless of whether they are marked {@link Consumer} or {@link Provider}. + * + * @see Provider + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.TYPE, ElementType.PACKAGE } ) +public @interface Consumer +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java new file mode 100644 index 000000000000..bb706d893fdb --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This annotation tags types that are part of an experimental API. + * Classes or methods annotated with this annotation may be changed / removed without notice. + * + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Experimental +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java new file mode 100644 index 000000000000..9813f69d5b22 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java @@ -0,0 +1,39 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation indicates that a type is automatically generated. + * + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +public @interface Generated +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java new file mode 100644 index 000000000000..ea8df9a06940 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java @@ -0,0 +1,43 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@code Immutable} annotation indicates that the object is immutable, i.e. + * none of its field can be changed. This also ensures that the type is + * {@link ThreadSafe}. + * + * @see ThreadSafe + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@ThreadSafe +@Target( ElementType.TYPE ) +public @interface Immutable +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java new file mode 100644 index 000000000000..0668a3bc8fdb --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java @@ -0,0 +1,44 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The annotated element must not be null. + *

+ * Annotated fields must not be null after construction has completed. + *

+ * When this annotation is applied to a method it applies to the method return value. + * + * @see Nullable + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD } ) +public @interface Nonnull +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java new file mode 100644 index 000000000000..ae4a6286fff7 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java @@ -0,0 +1,41 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation indicates that the annotated type is not threadsafe + * and should only be used by a single thread. + * + * @see ThreadSafe + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +public @interface NotThreadSafe +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java new file mode 100644 index 000000000000..e21a6de6a744 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * The annotated element can be {@code null}. + * + * @see Nonnull + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Nullable +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java new file mode 100644 index 000000000000..ea5174def81b --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * A type implemented by, or extended by maven itself. + * Maven provides implementations of those types and may inject them in plugins. + *

+ * A type can be marked {@link Consumer} or {@link Provider} but not both. A type is assumed to be + * {@link Consumer} if it is not marked either {@link Consumer} or {@link Provider}. + *

+ * A package can be marked {@link Provider}. In this case, all types in the package are considered + * to be a provider type regardless of whether they are marked {@link Consumer} or {@link Provider}. + * + * @see Consumer + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.TYPE, ElementType.PACKAGE } ) +public @interface Provider +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java new file mode 100644 index 000000000000..82d7b8463bc4 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * The {@code ThreadSafe} annotation can be used to indicate a given type + * is thread safe. {@link Immutable} objects are automatically thread safe. + * + * @see Immutable + * @see NotThreadSafe + * @since 4.0 + */ +@Experimental +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +public @interface ThreadSafe +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java new file mode 100644 index 000000000000..2a0d276c784d --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java @@ -0,0 +1,30 @@ +// CHECKSTYLE_OFF: RegexpHeader +/** + * This package contains non-functional annotations which are + * used to tag various elements and help users understanding + * how those types should be used. + * + * @since 4.0 + */ +@Experimental +package org.apache.maven.api.annotations; + +/* + * 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. + */ + diff --git a/api/maven-api-model/pom.xml b/api/maven-api-model/pom.xml new file mode 100644 index 000000000000..a62c6c72b2ae --- /dev/null +++ b/api/maven-api-model/pom.xml @@ -0,0 +1,104 @@ + + + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-model + + Maven API Model + Maven API Model for Maven POM (Project Object Model) + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + attach-mdo + + attach-artifact + + + + + src/main/mdo/maven.mdo + mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + 5.0.0 + + src/main/mdo/maven.mdo + + + + + + packageModelV4=org.apache.maven.api.model + + + + + modello + + velocity + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + + + + + diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java new file mode 100644 index 000000000000..35c98d6e7e8e --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Map.Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Map.Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java new file mode 100644 index 000000000000..5aff705b024b --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -0,0 +1,199 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Class InputLocation. + */ +public class InputLocation + implements Serializable, InputLocationTracker +{ + private final int lineNumber; + private final int columnNumber; + private final InputSource source; + private final Map locations; + + public InputLocation( InputSource source ) + { + this.lineNumber = -1; + this.columnNumber = -1; + this.source = source; + this.locations = Collections.singletonMap( 0, this ); + } + + public InputLocation( int lineNumber, int columnNumber ) + { + this( lineNumber, columnNumber, null, null ); + } + + public InputLocation( int lineNumber, int columnNumber, InputSource source ) + { + this( lineNumber, columnNumber, source, null ); + } + + public InputLocation( int lineNumber, int columnNumber, InputSource source, Object selfLocationKey ) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.source = source; + this.locations = selfLocationKey != null + ? Collections.singletonMap( selfLocationKey, this ) : Collections.emptyMap(); + } + + public InputLocation( int lineNumber, int columnNumber, InputSource source, Map locations ) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.source = source; + this.locations = ImmutableCollections.copy( locations ); + } + + public int getLineNumber() + { + return lineNumber; + } + + public int getColumnNumber() + { + return columnNumber; + } + + public InputSource getSource() + { + return source; + } + + public InputLocation getLocation( Object key ) + { + return locations != null ? locations.get( key ) : null; + } + + public Map getLocations() + { + return locations; + } + + /** + * Method merge. + */ + public static InputLocation merge( InputLocation target, InputLocation source, boolean sourceDominant ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + Map locations; + Map sourceLocations = source.locations; + Map targetLocations = target.locations; + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new LinkedHashMap<>(); + locations.putAll( sourceDominant ? targetLocations : sourceLocations ); + locations.putAll( sourceDominant ? sourceLocations : targetLocations ); + } + + return new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations ); + } //-- InputLocation merge( InputLocation, InputLocation, boolean ) + + /** + * Method merge. + */ + public static InputLocation merge( InputLocation target, InputLocation source, Collection indices ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + Map locations; + Map sourceLocations = source.locations; + Map targetLocations = target.locations; + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new LinkedHashMap<>(); + for ( int index : indices ) + { + InputLocation location; + if ( index < 0 ) + { + location = sourceLocations.get( ~index ); + } + else + { + location = targetLocations.get( index ); + } + locations.put( locations.size(), location ); + } + } + + return new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations ); + } //-- InputLocation merge( InputLocation, InputLocation, java.util.Collection ) + + /** + * Class StringFormatter. + * + * @version $Revision$ $Date$ + */ + public interface StringFormatter + { + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method toString. + */ + String toString( InputLocation location ); + + } + +} diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java new file mode 100644 index 000000000000..e90934813ab8 --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java @@ -0,0 +1,26 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +public interface InputLocationTracker +{ + InputLocation getLocation( Object field ); +} + diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java new file mode 100644 index 000000000000..34c8bf642a6f --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +import java.io.Serializable; + +/** + * Class InputSource. + */ +public class InputSource + implements Serializable +{ + + private final String modelId; + private final String location; + + public InputSource( String modelId, String location ) + { + this.modelId = modelId; + this.location = location; + } + + /** + * Get the path/URL of the POM or {@code null} if unknown. + */ + public String getLocation() + { + return this.location; + } + + /** + * Get the identifier of the POM in the format {@code ::}. + */ + public String getModelId() + { + return this.modelId; + } + + @Override + public String toString() + { + return getModelId() + " " + getLocation(); + } +} diff --git a/maven-model/src/main/java/org/apache/maven/model/package-info.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/package-info.java similarity index 96% rename from maven-model/src/main/java/org/apache/maven/model/package-info.java rename to api/maven-api-model/src/main/java/org/apache/maven/api/model/package-info.java index 88d3fa0701e6..bfcdbe273c51 100644 --- a/maven-model/src/main/java/org/apache/maven/model/package-info.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/package-info.java @@ -3,7 +3,7 @@ * Maven POM (Project Object Model) classes, generated from maven.mdo model. * The root class is {@link org.apache.maven.model.Model}. */ -package org.apache.maven.model; +package org.apache.maven.api.model; /* * Licensed to the Apache Software Foundation (ASF) under one diff --git a/api/maven-api-model/src/main/mdo/common.vm b/api/maven-api-model/src/main/mdo/common.vm new file mode 100644 index 000000000000..3c3f29cf7a27 --- /dev/null +++ b/api/maven-api-model/src/main/mdo/common.vm @@ -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. +*# +# +## +## The following loop code is required in order to change the type of the +## pomFile attribute to a java.nio.file.Path. Modello does not support this +## type and loading a model with such a type would fail the modello validation. +## +#foreach ( $field in $model.getClass("Model", $version).allFields ) + #if ( $field.name == "pomFile" ) + #set ( $dummy = $field.setType("java.nio.file.Path") ) + #end +#end +#set ( $locationTracking = true ) +# \ No newline at end of file diff --git a/maven-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo similarity index 84% rename from maven-model/src/main/mdo/maven.mdo rename to api/maven-api-model/src/main/mdo/maven.mdo index b669128b2585..7bd835d0987b 100644 --- a/maven-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -66,18 +66,26 @@ - + Model ModelBase <project> element is the root of the descriptor. + The {@code } element is the root of the descriptor. The following table lists all of the possible child elements. ]]> 3.0.0+ + + pomFile + 5.0.0+ + false + Originating POM file + DOM + + @@ -117,7 +125,7 @@ org.apache.maven). + projects with a similar name (eg. {@code org.apache.maven}). ]]> String @@ -144,10 +152,10 @@ 4.0.0+ jar - war - ear - pom. + The type of artifact this project produces, for example {@code jar} + {@code war} + {@code ear} + {@code pom}. Plugins can create their own packaging, and therefore their own packaging types, so this list does not contain all possible types. @@ -185,7 +193,7 @@ Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - project's child.project.url.inherit.append.path="false" + project's {@code child.project.url.inherit.append.path="false"} ]]> String @@ -196,9 +204,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -229,7 +237,7 @@ license element, which + Each license is described by a {@code license} element, which is then described by additional elements. Projects should only list the license(s) that applies to the project and not the licenses that apply to dependencies. @@ -353,19 +361,9 @@
- 4.0.0+ + 4.0.0/4.1.0 groupId:artifactId:packaging:version + * @return the model id as {@code groupId:artifactId:packaging:version} */ public String getId() { @@ -416,22 +419,62 @@ { return getId(); } + + public boolean isChildProjectUrlInheritAppendPath() + { + return getDelegate().isChildProjectUrlInheritAppendPath(); + } + + public void setChildProjectUrlInheritAppendPath( boolean childProjectUrlInheritAppendPath ) + { + delegate = getDelegate().withChildProjectUrlInheritAppendPath( String.valueOf( childProjectUrlInheritAppendPath ) ); + } + ]]> - 4.0.0+ + 5.0.0+ @@ -439,12 +482,12 @@
- + ModelBase 3.0.0+ Model and the Profile objects. + Base class for the {@code Model} and the {@code Profile} objects. ]]> @@ -476,7 +519,7 @@ <name>value</name>. + The format is {@code value}. ]]> Properties @@ -537,16 +580,6 @@ * - - reports - 4.0.0+ - - Deprecated. Now ignored by Maven. - ]]> - - DOM - reporting 4.0.0+ @@ -554,7 +587,7 @@ mvn site. + These reports will be run when a user executes {@code mvn site}. All of the reports will be included in the navigation bar for browsing. ]]> @@ -564,7 +597,7 @@
- + PluginContainer 3.0.0+ Contains the plugins informations for the project. @@ -584,10 +617,10 @@ 4.0.0+ pluginMap; + Map pluginMap; /** - * Reset the pluginsMap field to null + * Reset the {@code pluginsMap} field to {@code null} */ public synchronized void flushPluginMap() { @@ -595,17 +628,17 @@ } /** - * @return a Map of plugins field with Plugins#getKey() as key + * @return a Map of plugins field with {@code Plugins#getKey()} as key * @see org.apache.maven.model.Plugin#getKey() */ - public synchronized java.util.Map getPluginsAsMap() + public synchronized Map getPluginsAsMap() { if ( pluginMap == null ) { pluginMap = new java.util.LinkedHashMap(); - if ( plugins != null ) + if ( getPlugins() != null ) { - for ( java.util.Iterator it = plugins.iterator(); it.hasNext(); ) + for ( java.util.Iterator it = getPlugins().iterator(); it.hasNext(); ) { Plugin plugin = (Plugin) it.next(); pluginMap.put( plugin.getKey(), plugin ); @@ -664,7 +697,7 @@ This element describes all of the classpath resources such as properties files associated with a project. These resources are often included in the final package. - The default value is src/main/resources.]]> + The default value is {@code src/main/resources}.]]> Resource @@ -677,7 +710,7 @@ src/test/resources.]]> + The default value is {@code src/test/resources}.]]> Resource @@ -689,7 +722,7 @@ 4.0.0+ target.]]> + The default value is {@code target}.]]> String @@ -700,7 +733,7 @@ ${artifactId}-${version}. + The default value is {@code ${artifactId}-${version}}. ]]> String @@ -722,7 +755,7 @@ BuildBase <build> element contains informations required to build the project. + The {@code } element contains informations required to build the project. Default values are defined in Super POM. ]]> @@ -735,7 +768,7 @@ This element specifies a directory containing the source of the project. The generated build system will compile the sources from this directory when the project is built. The path given is relative to the project descriptor. - The default value is src/main/java.]]> + The default value is {@code src/main/java}.]]> String @@ -748,7 +781,7 @@ project. This directory is meant to be different from the sourceDirectory, in that its contents will be copied to the output directory in most cases (since scripts are interpreted rather than compiled). - The default value is src/main/scripts.]]> + The default value is {@code src/main/scripts}.]]> String @@ -760,7 +793,7 @@ This element specifies a directory containing the unit test source of the project. The generated build system will compile these directories when the project is being tested. The path given is relative to the project descriptor. - The default value is src/test/java.]]> + The default value is {@code src/test/java}.]]> String @@ -769,7 +802,7 @@ 4.0.0+ target/classes.]]> + The default value is {@code target/classes}.]]> String @@ -778,7 +811,7 @@ 4.0.0+ target/test-classes.]]> + The default value is {@code target/test-classes}.]]> String @@ -793,12 +826,12 @@ - + CiManagement 4.0.0+ <CiManagement> element contains informations required to the + The {@code } element contains informations required to the continuous integration system of the project. ]]> @@ -808,7 +841,7 @@ 4.0.0+ continuum. + The name of the continuous integration system, e.g. {@code continuum}. ]]> String @@ -832,7 +865,7 @@ - + Notifier Configures one method for notifying users/developers when a build breaks. 4.0.0+ @@ -894,7 +927,7 @@ - + Contributor Description of a person who has contributed to the project, but who does not have commit privileges. Usually, these contributions come in the form of patches submitted. @@ -939,7 +972,7 @@ role element, the body of which is a role name. This can also be used to + {@code role} element, the body of which is a role name. This can also be used to describe the contribution. ]]> @@ -972,12 +1005,12 @@ - + Dependency 3.0.0+ <dependency> element contains information about a dependency + The {@code } element contains information about a dependency of the project. ]]> @@ -989,7 +1022,7 @@ org.apache.maven. + {@code org.apache.maven}. ]]> String @@ -1001,7 +1034,7 @@ maven-artifact. + {@code maven-artifact}. ]]> String @@ -1011,7 +1044,7 @@ 3.0.0+ 3.2.1. In Maven 2, this can also be + The version of the dependency, e.g. {@code 3.2.1}. In Maven 2, this can also be specified as a range of versions. ]]> @@ -1023,8 +1056,8 @@ jar, war, ejb-client - and test-jar: see default + Some examples are {@code jar}, {@code war}, {@code ejb-client} + and {@code test-jar}: see default artifact handlers for a list. New types can be defined by extensions, so this is not a complete list. ]]> @@ -1039,11 +1072,11 @@ The classifier of the dependency. It is appended to the filename after the version. This allows:
    -
  • referring to attached artifact, for example sources and javadoc: +
  • referring to attached artifact, for example {@code sources} and {@code javadoc}: see default artifact handlers for a list,
  • distinguishing two artifacts that belong to the same POM but were built differently. - For example, jdk14 and jdk15.
  • + For example, {@code jdk14} and {@code jdk15}.
]]> @@ -1055,13 +1088,13 @@ 4.0.0+ compile, runtime, - test, system, and provided. Used to + The scope of the dependency - {@code compile}, {@code runtime}, + {@code test}, {@code system}, and {@code provided}. Used to calculate the various classpaths used for compilation, testing, and so on. It also assists in determining which artifacts to include in a distribution of this project. For more information, see the - dependency mechanism. The default scope is compile. + dependency mechanism. The default scope is {@code compile}. ]]> String @@ -1081,7 +1114,7 @@ for this dependency. Requires an absolute path for the value, not relative. Use a property that gives the machine specific absolute path, - e.g. ${java.home}. + e.g. {@code ${java.home}}. ]]> String @@ -1104,8 +1137,8 @@ Indicates the dependency is optional for use of this library. While the version of the dependency will be taken into account for dependency calculation if the library is used elsewhere, it will not be passed on transitively. Note: While the type - of this field is String for technical reasons, the semantic type is actually - Boolean. Default value is false. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> String @@ -1118,20 +1151,34 @@ + + + + 4.0.0/4.1.0 + + + + + + 4.0.0+ + + @@ -1140,27 +1187,19 @@ 4.0.0+ groupId:artifactId:type + * @return the management key as {@code groupId:artifactId:type} */ public String getManagementKey() { if ( managementKey == null ) { - managementKey = groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" ); + managementKey = getGroupId() + ":" + getArtifactId() + ":" + getType() + ( getClassifier() != null ? ":" + getClassifier() : "" ); } return managementKey; } - - /** - * Clears the management key in case one field has been modified. - */ - public void clearManagementKey() - { - managementKey = null; - } ]]> @@ -1180,12 +1219,12 @@
- + Exclusion 4.0.0+ <exclusion> element contains informations required to exclude + The {@code } element contains informations required to exclude an artifact to the project. ]]> @@ -1206,7 +1245,7 @@ - + IssueManagement Information about the issue tracking (or bug tracking) system used to manage this project. @@ -1226,7 +1265,7 @@ - + DistributionManagement 4.0.0+ This elements describes all that pertains to distribution for a project. It is @@ -1247,7 +1286,7 @@ repository element. + {@code repository} element. ]]> @@ -1268,7 +1307,7 @@ url. + referred to the homepage given by {@code url}. This is given to assist in locating artifacts that are not in the repository due to licensing restrictions. ]]> @@ -1291,11 +1330,11 @@ none (default), - converted (repository manager converted this from an Maven 1 POM), - partner - (directly synced from a partner Maven 2 repository), deployed (was deployed from a Maven 2 - instance), verified (has been hand verified as correct and final). + tools placing it in the reposiory. Valid values are: {@code none} (default), + {@code converted} (repository manager converted this from an Maven 1 POM), + {@code partner} + (directly synced from a partner Maven 2 repository), {@code deployed} (was deployed from a Maven 2 + instance), {@code verified} (has been hand verified as correct and final). ]]> false @@ -1303,7 +1342,7 @@ - + License Describes the licenses for this project. This is used to generate the license page of the project's web site, as well as being taken into consideration in other reporting @@ -1347,7 +1386,7 @@ - + MailingList 3.0.0+ This element describes all of the mailing lists associated with a project. The @@ -1370,7 +1409,7 @@ mailto: link will automatically be created + {@code mailto:} link will automatically be created when the documentation is created. ]]> @@ -1383,7 +1422,7 @@ mailto: link will automatically be created + {@code mailto:} link will automatically be created when the documentation is created. ]]> @@ -1396,7 +1435,7 @@ mailto: link will automatically be created + {@code mailto:} link will automatically be created when the documentation is created. ]]> @@ -1422,7 +1461,7 @@ and maybe even a specific element for the user and scm mailing lists. Then leave the more lose structure for any other type of mailing list. - + Organization Specifies the organization that produces this project. 3.0.0+ @@ -1441,7 +1480,7 @@ - + PatternSet 3.0.0+ Definition of include or exclude patterns. @@ -1451,7 +1490,7 @@ 3.0.0+ **/*.xml. + A list of patterns to include, e.g. {@code **/*.xml}. ]]> @@ -1464,7 +1503,7 @@ 3.0.0+ **/*.xml + A list of patterns to exclude, e.g. {@code **/*.xml} ]]> @@ -1509,12 +1548,12 @@ - + Parent 4.0.0+ <parent> element contains information required to locate the parent project from which + The {@code } element contains information required to locate the parent project from which this project will inherit from. Note: The children of this element are not interpolated and must be given as literal values. ]]> @@ -1545,11 +1584,11 @@ 4.0.0+ pom.xml file within the check out. - If not specified, it defaults to ../pom.xml. + The relative path of the parent {@code pom.xml} file within the check out. + If not specified, it defaults to {@code ../pom.xml}. Maven looks for the parent POM first in this location on the filesystem, then the local repository, and lastly in the remote repo. - relativePath allows you to select a different location, + {@code relativePath} allows you to select a different location, for example when your structure is flat, or deeper without an intermediate parent POM. However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM. @@ -1568,7 +1607,7 @@ groupId:artifactId:version + * @return the id as {@code groupId:artifactId:version} */ public String getId() { @@ -1596,12 +1635,12 @@ - + Scm 4.0.0+ <scm> element contains informations required to the SCM + The {@code } element contains informations required to the SCM (Source Control Management) of the project. ]]> @@ -1618,7 +1657,7 @@ and list of supported SCMs. This connection is read-only.
Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - scm's child.scm.connection.inherit.append.path="false" + scm's {@code child.scm.connection.inherit.append.path="false"} ]]> String @@ -1628,10 +1667,10 @@ 4.0.0+ connection, but for developers, i.e. this scm connection + Just like {@code connection}, but for developers, i.e. this scm connection will not be read only.
Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - scm's child.scm.developerConnection.inherit.append.path="false" + scm's {@code child.scm.developerConnection.inherit.append.path="false"} ]]>
String @@ -1650,7 +1689,7 @@ Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - scm's child.scm.url.inherit.append.path="false" + scm's {@code child.scm.url.inherit.append.path="false"} ]]> String @@ -1661,9 +1700,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -1675,9 +1714,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -1689,9 +1728,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -1706,32 +1745,17 @@ public boolean isChildScmConnectionInheritAppendPath() { - return ( childScmConnectionInheritAppendPath != null ) ? Boolean.parseBoolean( childScmConnectionInheritAppendPath ) : true; - } - - public void setChildScmConnectionInheritAppendPath( boolean childScmConnectionInheritAppendPath ) - { - this.childScmConnectionInheritAppendPath = String.valueOf( childScmConnectionInheritAppendPath ); + return ( getChildScmConnectionInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildScmConnectionInheritAppendPath() ) : true; } public boolean isChildScmDeveloperConnectionInheritAppendPath() { - return ( childScmDeveloperConnectionInheritAppendPath != null ) ? Boolean.parseBoolean( childScmDeveloperConnectionInheritAppendPath ) : true; - } - - public void setChildScmDeveloperConnectionInheritAppendPath( boolean childScmDeveloperConnectionInheritAppendPath ) - { - this.childScmDeveloperConnectionInheritAppendPath = String.valueOf( childScmDeveloperConnectionInheritAppendPath ); + return ( getChildScmDeveloperConnectionInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildScmDeveloperConnectionInheritAppendPath() ) : true; } public boolean isChildScmUrlInheritAppendPath() { - return ( childScmUrlInheritAppendPath != null ) ? Boolean.parseBoolean( childScmUrlInheritAppendPath ) : true; - } - - public void setChildScmUrlInheritAppendPath( boolean childScmUrlInheritAppendPath ) - { - this.childScmUrlInheritAppendPath = String.valueOf( childScmUrlInheritAppendPath ); + return ( getChildScmUrlInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildScmUrlInheritAppendPath() ) : true; } ]]> @@ -1783,10 +1807,10 @@ ${project.build.outputDirectory}). + directory (i.e. {@code ${project.build.outputDirectory}}). For example, if you want that resource to appear in a specific package - (org.apache.maven.messages), you must specify this - element with this value: org/apache/maven/messages. + ({@code org.apache.maven.messages}), you must specify this + element with this value: {@code org/apache/maven/messages}. This is not required if you simply put the resources in that directory structure at the source, however. ]]> @@ -1799,10 +1823,10 @@ properties element and from the - properties in the files listed in the filters element. Note: While the type - of this field is String for technical reasons, the semantic type is actually - Boolean. Default value is false. + The values are taken from the {@code properties} element and from the + properties in the files listed in the {@code filters} element. Note: While the type + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> String @@ -1827,26 +1851,28 @@ 4.0.0+ + + + + 4.0.0/4.1.0 + + + + + + 4.0.0+ + +
- + RepositoryBase 4.0.0+ A repository contains the information needed for establishing connections with @@ -1873,7 +1899,7 @@ settings.xml file, for example. Furthermore, the identifier is + to configuration in the {@code settings.xml} file, for example. Furthermore, the identifier is used during POM inheritance and profile injection to detect repositories that should be merged. ]]> @@ -1891,7 +1917,7 @@ true protocol://hostname/path. + The url of the repository, in the form {@code protocol://hostname/path}. ]]> String @@ -1902,7 +1928,7 @@ legacy or default. + can be {@code legacy} or {@code default}. ]]> String @@ -1955,7 +1981,7 @@
- + RepositoryPolicy 4.0.0+ Download policy. @@ -1966,8 +1992,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is true. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code true}. ]]> String @@ -1978,12 +2004,12 @@ always, - daily + {@code always,} + {@code daily} (default), - interval:XXX + {@code interval:XXX} (in minutes) or - never + {@code never} (only if it doesn't exist locally). ]]> @@ -1995,10 +2021,10 @@ ignore, - fail + {@code ignore}, + {@code fail} (default for Maven 4 and above) or - warn + {@code warn} (default for Maven 2 and 3) ]]> @@ -2010,15 +2036,21 @@ 4.0.0+ + + + + 4.0.0/4.1.0 + + @@ -2028,7 +2060,7 @@ - + Site 4.0.0+ Contains the information needed for deploying websites. @@ -2039,7 +2071,7 @@ settings.xml file, for example. + site to configuration in the {@code settings.xml} file, for example. ]]> String @@ -2055,9 +2087,9 @@ 4.0.0+ protocol://hostname/path. + The url of the location where website is deployed, in the form {@code protocol://hostname/path}.
Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - site's child.site.url.inherit.append.path="false" + site's {@code child.site.url.inherit.append.path="false"} ]]>
String @@ -2068,9 +2100,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -2085,12 +2117,7 @@ public boolean isChildSiteUrlInheritAppendPath() { - return ( childSiteUrlInheritAppendPath != null ) ? Boolean.parseBoolean( childSiteUrlInheritAppendPath ) : true; - } - - public void setChildSiteUrlInheritAppendPath( boolean childSiteUrlInheritAppendPath ) - { - this.childSiteUrlInheritAppendPath = String.valueOf( childSiteUrlInheritAppendPath ); + return ( getChildSiteUrlInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildSiteUrlInheritAppendPath() ) : true; } ]]> @@ -2099,7 +2126,7 @@
- + ConfigurationContainer 4.0.0+ Contains the configuration information of the container like Plugin. @@ -2110,8 +2137,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is true. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code true}. ]]> String @@ -2121,12 +2148,12 @@ The configuration as DOM object.

By default, every element content is trimmed, but starting with Maven 3.1.0, you can add - xml:space="preserve" to elements you want to preserve whitespace.

-

You can control how child POMs inherit configuration from parent POMs by adding combine.children - or combine.self attributes to the children of the configuration element:

+ {@code xml:space="preserve"} to elements you want to preserve whitespace.

+

You can control how child POMs inherit configuration from parent POMs by adding {@code combine.children} + or {@code combine.self} attributes to the children of the configuration element:

    -
  • combine.children: available values are merge (default) and append,
  • -
  • combine.self: available values are merge (default) and override.
  • +
  • {@code combine.children}: available values are {@code merge} (default) and {@code append},
  • +
  • {@code combine.self}: available values are {@code merge} (default) and {@code override}.

See POM Reference documentation and Xpp3DomUtils @@ -2144,25 +2171,9 @@ @@ -2174,7 +2185,7 @@ ConfigurationContainer <plugin> element contains informations required for a plugin. + The {@code } element contains informations required for a plugin. ]]> @@ -2206,8 +2217,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is false. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> @@ -2231,16 +2242,6 @@ * - - goals - 4.0.0+ - - Deprecated. Unused by Maven. - ]]> - - DOM - @@ -2249,26 +2250,37 @@ + + + + 4.0.0/4.1.0 + + + + + + 4.0.0+ + + executionMap = null; /** - * Reset the executionMap field to null + * Reset the {@code executionMap} field to {@code null} */ public void flushExecutionMap() { this.executionMap = null; } - /** - * @return a Map of executions field with PluginExecution#getId() as key + * @return a Map of executions field with {@code PluginExecution#getId()} as key * @see org.apache.maven.model.PluginExecution#getId() */ public java.util.Map getExecutionsAsMap() @@ -2276,22 +2288,16 @@ if ( executionMap == null ) { executionMap = new java.util.LinkedHashMap(); - if ( getExecutions() != null ) + for ( java.util.Iterator i = getExecutions().iterator(); i.hasNext(); ) { - for ( java.util.Iterator i = getExecutions().iterator(); i.hasNext(); ) + PluginExecution exec = (PluginExecution) i.next(); + if ( executionMap.containsKey( exec.getId() ) ) { - PluginExecution exec = (PluginExecution) i.next(); - - if ( executionMap.containsKey( exec.getId() ) ) - { - throw new IllegalStateException( "You cannot have two plugin executions with the same (or missing) elements.\nOffending execution\n\nId: \'" + exec.getId() + "\'\nPlugin:\'" + getKey() + "\'\n\n" ); - } - - executionMap.put( exec.getId(), exec ); + throw new IllegalStateException( "You cannot have two plugin executions with the same (or missing) elements.\nOffending execution\n\nId: \'" + exec.getId() + "\'\nPlugin:\'" + getKey() + "\'\n\n" ); } + executionMap.put( exec.getId(), exec ); } } - return executionMap; } @@ -2314,17 +2320,17 @@ } /** - * @return the key of the plugin, ie groupId:artifactId + * @return the key of the plugin, ie {@code groupId:artifactId} */ public String getKey() { - return constructKey( groupId, artifactId ); + return constructKey( getGroupId(), getArtifactId() ); } /** * @param groupId The group ID of the plugin in the repository * @param artifactId The artifact ID of the reporting plugin in the repository - * @return the key of the plugin, ie groupId:artifactId + * @return the key of the plugin, ie {@code groupId:artifactId} */ public static String constructKey( String groupId, String artifactId ) { @@ -2372,7 +2378,7 @@ ConfigurationContainer <execution> element contains informations required for the + The {@code } element contains informations required for the execution of a plugin. ]]> @@ -2432,7 +2438,7 @@ - + DependencyManagement 4.0.0+ Section for management of default dependency information for use in a group of @@ -2458,7 +2464,7 @@ Section for management of default plugin information for use in a group of POMs. - + Reporting 4.0.0+ Section for management of reports and their configuration. @@ -2471,8 +2477,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is false. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> @@ -2483,7 +2489,7 @@ ${project.build.directory}/site. + {@code ${project.build.directory}/site}. ]]> @@ -2505,45 +2511,21 @@ + + + + 4.0.0/4.1.0 + + reportPluginMap; - - /** - * Reset the reportPluginMap field to null - */ - public synchronized void flushReportPluginMap() - { - this.reportPluginMap = null; - } - - /** - * @return a Map of plugins field with ReportPlugin#getKey() as key - * @see org.apache.maven.model.ReportPlugin#getKey() - */ - public synchronized java.util.Map getReportPluginsAsMap() - { - if ( reportPluginMap == null ) - { - reportPluginMap = new java.util.LinkedHashMap(); - if ( getPlugins() != null ) - { - for ( java.util.Iterator it = getPlugins().iterator(); it.hasNext(); ) - { - ReportPlugin reportPlugin = (ReportPlugin) it.next(); - reportPluginMap.put( reportPlugin.getKey(), reportPlugin ); - } - } - } - - return reportPluginMap; - } ]]> @@ -2588,7 +2570,35 @@ - 4.0.0+ + 4.0.0/4.1.0 + + + + + + 5.0.0+ - + Activation 4.0.0+ The conditions within the build runtime environment which will trigger the @@ -2644,9 +2654,9 @@ 1.4 only activates on JDKs versioned 1.4, - while !1.4 matches any JDK that is not version 1.4. Ranges are supported too: - [1.5,) activates when the JDK is 1.5 minimum. + For example, {@code 1.4} only activates on JDKs versioned 1.4, + while {@code !1.4} matches any JDK that is not version 1.4. Ranges are supported too: + {@code [1.5,)} activates when the JDK is 1.5 minimum. ]]> @@ -2690,7 +2700,7 @@ --> - + ActivationProperty 4.0.0+ This is the property specification used to activate a profile. If the value field @@ -2712,7 +2722,7 @@ - + ActivationOS 4.0.0+ This is an activator which will detect an operating system's attributes in order @@ -2725,7 +2735,7 @@ ${os.name} Java property, such as Windows XP. + of the {@code ${os.name}} Java property, such as {@code Windows XP}. ]]> @@ -2736,7 +2746,7 @@ windows or unix. + {@code windows} or {@code unix}. ]]> @@ -2756,14 +2766,14 @@ - + ActivationFile 4.0.0+ - missing value + exists will test for the existence of the file and if it is + activated. On the other hand, {@code exists} will test for the existence of the file and if it is there, the profile will be activated.
- Variable interpolation for these file specifications is limited to ${basedir}, + Variable interpolation for these file specifications is limited to {@code ${basedir}}, System properties and request properties.]]>
@@ -2812,7 +2822,7 @@ ConfigurationContainer <plugin> element in <reporting><plugins> contains informations required for a report plugin. + The {@code } element in {@code } contains informations required for a report plugin. ]]> @@ -2836,8 +2846,8 @@ 4.0.0+ build/plugins then in build/pluginManagement. + The version of the reporting plugin to be used. Starting with Maven 3, if no version is defined explicitely, + version is searched in {@code build/plugins} then in {@code build/pluginManagement}. ]]> String @@ -2848,7 +2858,7 @@ execution in the build. + configuration. This is the reporting parallel to an {@code execution} in the build. ]]> @@ -2865,7 +2875,7 @@ private java.util.Map reportSetMap = null; /** - * Reset the reportSetMap field to null + * Reset the {@code reportSetMap} field to {@code null} */ public void flushReportSetMap() { @@ -2873,7 +2883,7 @@ } /** - * @return a Map of reportSets field with ReportSet#getId() as key + * @return a Map of reportSets field with {@code ReportSet#getId()} as key * @see org.apache.maven.model.ReportSet#getId() */ public java.util.Map getReportSetsAsMap() @@ -2895,17 +2905,17 @@ } /** - * @return the key of the report plugin, ie groupId:artifactId + * @return the key of the report plugin, ie {@code groupId:artifactId} */ public String getKey() { - return constructKey( groupId, artifactId ); + return constructKey( getGroupId(), getArtifactId() ); } /** * @param groupId The group ID of the plugin in the repository * @param artifactId The artifact ID of the reporting plugin in the repository - * @return the key of the report plugin, ie groupId:artifactId + * @return the key of the report plugin, ie {@code groupId:artifactId} */ public static String constructKey( String groupId, String artifactId ) { @@ -2916,7 +2926,7 @@
- + ReportSet 4.0.0+ ConfigurationContainer @@ -2957,7 +2967,7 @@ - + Prerequisites 4.0.0+ Describes the prerequisites a project can have. @@ -2968,19 +2978,19 @@ String 2.0 maven-plugin), the minimum version of + For a plugin project (packaging is {@code maven-plugin}), the minimum version of Maven required to use the resulting plugin.
In Maven 2, this was also specifying the minimum version of Maven required to build a project, but this usage is deprecated in Maven 3 and not checked any more: use the Maven Enforcer Plugin's - requireMavenVersion rule instead. + {@code requireMavenVersion} rule instead. ]]>
false
- + Relocation 4.0.0+ Describes where an artifact has moved to. If any of the values are omitted, it is @@ -3012,7 +3022,7 @@ - + Extension 4.0.0+ Describes a build extension to utilise. @@ -3096,7 +3106,7 @@ - + InputLocation 4.0.0+ @@ -3118,7 +3128,7 @@ - + InputSource 4.0.0+ diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm new file mode 100644 index 000000000000..9b3c2382ed0e --- /dev/null +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -0,0 +1,529 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Experimental +@Generated @ThreadSafe @Immutable +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else + implements Serializable + #end +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ + final ${type} $field.name; + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + InputLocation location${sep} + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} + #end + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + #set ( $sep = "#if(${inheritedFields.size()}>0),#end" ) + location${sep} + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else + this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end + #end + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull + public ${class.name} with${cap}( $type $field.name ) + { + return with().${field.name}( $field.name ).build(); + } + #end + + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull + public static Builder newBuilder() + { + return newBuilder( true ); + } + + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + @Nonnull + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull + public Builder ${field.name}( ${type} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + #if ( $locationTracking ) + Map locations = null; + InputLocation location = null; + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = null; + #end + if ( this.locations != null ) + { + locations = this.locations; + location = locations.remove( "" ); + #foreach ( $field in $allFields ) + ${field.name}Location = locations.remove( "${field.name}" ); + #end + } + #end + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + #if ( $locationTracking ) + locations != null ? locations : ( base != null ? base.locations : null ), + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + location != null ? location : ( base != null ? base.location : null )${sep} + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml new file mode 100644 index 000000000000..e6b3c9c0ebbc --- /dev/null +++ b/api/maven-api-settings/pom.xml @@ -0,0 +1,104 @@ + + + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-settings + + Maven API Settings + Maven API Settings model. + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + attach-mdo + + attach-artifact + + + + + src/main/mdo/settings.mdo + mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + 2.0.0 + + src/main/mdo/settings.mdo + + + + + + packageModelV4=org.apache.maven.api.settings + + + + + modello + + velocity + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + + + + + diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java new file mode 100644 index 000000000000..850e0ef6659a --- /dev/null +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.api.settings; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/api/maven-api-settings/src/main/mdo/common.vm b/api/maven-api-settings/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/api/maven-api-settings/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm new file mode 100644 index 000000000000..4eb6f450672f --- /dev/null +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -0,0 +1,521 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Experimental +@Generated @ThreadSafe @Immutable +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else + implements Serializable + #end +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ + final ${type} $field.name; + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + InputLocation location${sep} + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} + #end + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + #set ( $sep = "#if(${inheritedFields.size()}>0),#end" ) + location${sep} + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else + this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end + #end + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull + public ${class.name} with${cap}( $type $field.name ) + { + return with().${field.name}( $field.name ).build(); + } + #end + + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull + public static Builder newBuilder() + { + return newBuilder( true ); + } + + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + @Nonnull + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull + public Builder ${field.name}( ${type} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + #if ( $locationTracking ) + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + #end + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + #if ( $locationTracking ) + locations, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + location != null ? location : ( base != null ? base.location : null )${sep} + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-settings/src/main/mdo/settings.mdo b/api/maven-api-settings/src/main/mdo/settings.mdo similarity index 99% rename from maven-settings/src/main/mdo/settings.mdo rename to api/maven-api-settings/src/main/mdo/settings.mdo index 4500560ca601..6a5757bb89dd 100644 --- a/maven-settings/src/main/mdo/settings.mdo +++ b/api/maven-api-settings/src/main/mdo/settings.mdo @@ -654,9 +654,9 @@ StringBuilder sb = new StringBuilder( 128 ); sb.append( "Mirror[" ); sb.append( "id=" ).append( this.getId() ); - sb.append( ",mirrorOf=" ).append( mirrorOf ); - sb.append( ",url=" ).append( this.url ); - sb.append( ",name=" ).append( this.name ); + sb.append( ",mirrorOf=" ).append( this.getMirrorOf() ); + sb.append( ",url=" ).append( this.getUrl() ); + sb.append( ",name=" ).append( this.getName() ); if ( isBlocked() ) { sb.append( ",blocked" ); @@ -874,14 +874,11 @@ public boolean equals( Object obj ) { RepositoryBase other = (RepositoryBase) obj; - boolean retValue = false; - - if ( id != null ) + if ( this.getId() != null ) { - retValue = id.equals( other.id ); + retValue = this.getId().equals( other.getId() ); } - return retValue; } ]]> diff --git a/api/maven-api-settings/src/site/apt/index.apt b/api/maven-api-settings/src/site/apt/index.apt new file mode 100644 index 000000000000..2b42ccd16a36 --- /dev/null +++ b/api/maven-api-settings/src/site/apt/index.apt @@ -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. + + ----- + Introduction + ----- + Vincent Siveton + ----- + 2006-11-04 + ----- + +Maven Settings Model + + This is strictly the model for Maven settings. + + The following are generated from this model: + + * {{{./apidocs/index.html}Java sources}} with Reader and Writers for the Xpp3 XML parser + + * A {{{./settings.html}Descriptor Reference}} + + * An {{{https://maven.apache.org/xsd/settings-1.2.0.xsd}XSD}} diff --git a/api/maven-api-settings/src/site/site.xml b/api/maven-api-settings/src/site/site.xml new file mode 100644 index 000000000000..e475330c4063 --- /dev/null +++ b/api/maven-api-settings/src/site/site.xml @@ -0,0 +1,38 @@ + + + + + + + ${project.scm.url} + + + + + + + + + + + + + \ No newline at end of file diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml new file mode 100644 index 000000000000..cba137cf612f --- /dev/null +++ b/api/maven-api-toolchain/pom.xml @@ -0,0 +1,105 @@ + + + + + + + maven-api + org.apache.maven + 4.0.0-alpha-1-SNAPSHOT + + 4.0.0 + + maven-api-toolchain + + Maven API Toolchain + Maven API Toolchain model. + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + attach-mdo + + attach-artifact + + + + + src/main/mdo/toolchains.mdo + mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + 1.1.0 + + src/main/mdo/toolchains.mdo + + + + + + packageModelV4=org.apache.maven.api.toolchain + + + + + modello + + velocity + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + + + + + diff --git a/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java new file mode 100644 index 000000000000..934a40331681 --- /dev/null +++ b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.api.toolchain; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/api/maven-api-toolchain/src/main/mdo/common.vm b/api/maven-api-toolchain/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/api/maven-api-toolchain/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm new file mode 100644 index 000000000000..4eb6f450672f --- /dev/null +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -0,0 +1,521 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Experimental +@Generated @ThreadSafe @Immutable +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else + implements Serializable + #end +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ + final ${type} $field.name; + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + InputLocation location${sep} + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} + #end + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + #set ( $sep = "#if(${inheritedFields.size()}>0),#end" ) + location${sep} + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else + this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end + #end + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull + public ${class.name} with${cap}( $type $field.name ) + { + return with().${field.name}( $field.name ).build(); + } + #end + + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull + public static Builder newBuilder() + { + return newBuilder( true ); + } + + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + @Nonnull + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull + public Builder ${field.name}( ${type} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + #if ( $locationTracking ) + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + #end + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + #if ( $locationTracking ) + locations, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + location != null ? location : ( base != null ? base.location : null )${sep} + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-toolchain-model/src/main/mdo/toolchains.mdo b/api/maven-api-toolchain/src/main/mdo/toolchains.mdo similarity index 98% rename from maven-toolchain-model/src/main/mdo/toolchains.mdo rename to api/maven-api-toolchain/src/main/mdo/toolchains.mdo index 29f742ccaa8f..7090b9468640 100644 --- a/maven-toolchain-model/src/main/mdo/toolchains.mdo +++ b/api/maven-api-toolchain/src/main/mdo/toolchains.mdo @@ -189,8 +189,8 @@ { int result = 17; - result = 37 * result + ( type != null ? type.hashCode() : 0 ); - result = 37 * result + ( provides != null ? provides.hashCode() : 0 ); + result = 37 * result + ( getType() != null ? getType().hashCode() : 0 ); + result = 37 * result + ( getProvides() != null ? getProvides().hashCode() : 0 ); return result; } //-- int hashCode() diff --git a/api/maven-api-xml/pom.xml b/api/maven-api-xml/pom.xml new file mode 100644 index 000000000000..42ad25007aeb --- /dev/null +++ b/api/maven-api-xml/pom.xml @@ -0,0 +1,40 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-xml + Maven API XML + + + + org.apache.maven + maven-api-meta + 4.0.0-alpha-1-SNAPSHOT + + + + diff --git a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java new file mode 100644 index 000000000000..2b8d63eae01b --- /dev/null +++ b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java @@ -0,0 +1,129 @@ +package org.apache.maven.api.xml; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.ThreadSafe; + +/** + * An immutable xml node. + * + * @since 4.0 + */ +@Experimental +@ThreadSafe @Immutable +public interface Dom +{ + + String CHILDREN_COMBINATION_MODE_ATTRIBUTE = "combine.children"; + + String CHILDREN_COMBINATION_MERGE = "merge"; + + String CHILDREN_COMBINATION_APPEND = "append"; + + /** + * This default mode for combining children DOMs during merge means that where element names match, the process will + * try to merge the element data, rather than putting the dominant and recessive elements (which share the same + * element name) as siblings in the resulting DOM. + */ + String DEFAULT_CHILDREN_COMBINATION_MODE = CHILDREN_COMBINATION_MERGE; + + String SELF_COMBINATION_MODE_ATTRIBUTE = "combine.self"; + + String SELF_COMBINATION_OVERRIDE = "override"; + + String SELF_COMBINATION_MERGE = "merge"; + + String SELF_COMBINATION_REMOVE = "remove"; + + /** + * This default mode for combining a DOM node during merge means that where element names match, the process will + * try to merge the element attributes and values, rather than overriding the recessive element completely with the + * dominant one. This means that wherever the dominant element doesn't provide the value or a particular attribute, + * that value or attribute will be set from the recessive DOM node. + */ + String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE; + + @Nonnull + String getName(); + + @Nullable + String getValue(); + + @Nonnull + Map getAttributes(); + + @Nullable + String getAttribute( @Nonnull String name ); + + @Nonnull + List getChildren(); + + @Nullable + Dom getChild( String name ); + + @Nullable + Object getInputLocation(); + + default Dom merge( @Nullable Dom source ) + { + return merge( source, (Boolean) null ); + } + + Dom merge( @Nullable Dom source, @Nullable Boolean childMergeOverride ); + + Dom clone(); + + /** + * Merge recessive into dominant and return either {@code dominant} + * with merged information or a clone of {@code recessive} if + * {@code dominant} is {@code null}. + * + * @param dominant the node + * @param recessive if {@code null}, nothing will happen + * @return the merged node + */ + @Nullable + static Dom merge( @Nullable Dom dominant, @Nullable Dom recessive ) + { + return merge( dominant, recessive, null ); + } + + @Nullable + static Dom merge( @Nullable Dom dominant, @Nullable Dom recessive, @Nullable Boolean childMergeOverride ) + { + if ( recessive == null ) + { + return dominant; + } + if ( dominant == null ) + { + return recessive; + } + return dominant.merge( recessive, childMergeOverride ); + } + +} diff --git a/api/modello-plugin-velocity/pom.xml b/api/modello-plugin-velocity/pom.xml new file mode 100644 index 000000000000..2875135e731c --- /dev/null +++ b/api/modello-plugin-velocity/pom.xml @@ -0,0 +1,98 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + modello-plugin-velocity + maven-plugin + Modello Velocity Plugin + + Modello Velocity Plugin generates custom templates. + + + + 3.6.4 + 3.8.5 + + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginTools} + provided + + + org.apache.maven + maven-plugin-api + ${maven} + provided + + + * + * + + + + + org.apache.maven + maven-core + ${maven} + provided + + + * + * + + + + + org.codehaus.modello + modello-maven-plugin + 2.0.0 + + + org.apache.velocity + velocity-engine-core + 2.3 + + + org.codehaus.modello + modello-core + 2.0.0 + + + org.codehaus.modello + modello-plugin-xml + 2.0.0 + + + org.codehaus.plexus + plexus-utils + + + + diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java new file mode 100644 index 000000000000..0e9f285fddc7 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java @@ -0,0 +1,154 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.codehaus.modello.ModelloRuntimeException; +import org.codehaus.modello.model.ModelAssociation; +import org.codehaus.modello.model.ModelClass; +import org.codehaus.modello.model.ModelField; +import org.codehaus.modello.model.Version; +import org.codehaus.modello.plugin.AbstractModelloGenerator; +import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata; +import org.codehaus.modello.plugins.xml.metadata.XmlClassMetadata; +import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata; +import org.codehaus.plexus.util.StringUtils; + +@SuppressWarnings( "unused" ) +public class Helper +{ + private final Version version; + + public Helper( Version version ) + { + this.version = version; + } + + public String capitalise( String str ) + { + return StringUtils.isEmpty( str ) ? str : Character.toTitleCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public String uncapitalise( String str ) + { + return StringUtils.isEmpty( str ) ? str : Character.toLowerCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public String singular( String str ) + { + return AbstractModelloGenerator.singular( str ); + } + + public List ancestors( ModelClass clazz ) + { + List ancestors = new ArrayList<>(); + for ( ModelClass cl = clazz; cl != null; cl = cl.getSuperClass() != null + ? cl.getModel().getClass( cl.getSuperClass(), version ) : null ) + { + ancestors.add( 0, cl ); + } + return ancestors; + } + + public XmlClassMetadata xmlClassMetadata( ModelClass clazz ) + { + return (XmlClassMetadata) clazz.getMetadata( XmlClassMetadata.ID ); + } + + public XmlFieldMetadata xmlFieldMetadata( ModelField field ) + { + return (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); + } + + public XmlAssociationMetadata xmAssociationMetadata( ModelField field ) + { + return (XmlAssociationMetadata) ( (ModelAssociation) field ) + .getAssociationMetadata( XmlAssociationMetadata.ID ); + } + + public boolean isFlatItems( ModelField field ) + { + return field instanceof ModelAssociation && xmAssociationMetadata( field ).isFlatItems(); + } + + public List xmlFields( ModelClass modelClass ) + { + List classes = new ArrayList<>(); + // get the full inheritance + while ( modelClass != null ) + { + classes.add( modelClass ); + String superClass = modelClass.getSuperClass(); + if ( superClass != null ) + { + // superClass can be located outside (not generated by modello) + modelClass = modelClass.getModel().getClass( superClass, version, true ); + } + else + { + modelClass = null; + } + } + List fields = new ArrayList<>(); + for ( int i = classes.size() - 1; i >= 0; i-- ) + { + modelClass = classes.get( i ); + Iterator parentIter = fields.iterator(); + fields = new ArrayList<>(); + for ( ModelField field : modelClass.getFields( version ) ) + { + XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); + if ( xmlFieldMetadata.isTransient() ) + { + // just ignore xml.transient fields + continue; + } + if ( xmlFieldMetadata.getInsertParentFieldsUpTo() != null ) + { + // insert fields from parent up to the specified field + boolean found = false; + while ( !found && parentIter.hasNext() ) + { + ModelField parentField = parentIter.next(); + fields.add( parentField ); + found = parentField.getName().equals( xmlFieldMetadata.getInsertParentFieldsUpTo() ); + } + if ( !found ) + { + // interParentFieldsUpTo not found + throw new ModelloRuntimeException( "parent field not found: class " + + modelClass.getName() + " xml.insertParentFieldUpTo='" + + xmlFieldMetadata.getInsertParentFieldsUpTo() + "'" ); + } + } + fields.add( field ); + } + // add every remaining fields from parent class + while ( parentIter.hasNext() ) + { + fields.add( parentIter.next() ); + } + } + return fields; + } +} diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java new file mode 100644 index 000000000000..604d54f542e7 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java @@ -0,0 +1,86 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.io.File; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.stream.Collectors; + +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.modello.maven.AbstractModelloGeneratorMojo; + +/** + * Creates an XML schema from the model. + * + * @author Brett Porter + */ +@Mojo( name = "velocity", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true ) +public class ModelloVelocityMojo + extends AbstractModelloGeneratorMojo +{ + /** + * The output directory of the generated XML Schema. + */ + @Parameter( defaultValue = "${project.build.directory}/generated-sources/modello", required = true ) + private File outputDirectory; + + @Parameter + private List templates; + + @Parameter + private List params; + + protected String getGeneratorType() + { + return "velocity"; + } + + protected void customizeParameters( Properties parameters ) + { + super.customizeParameters( parameters ); + Map params = this.params != null ? this.params.stream().collect( Collectors.toMap( + s -> s.substring( 0, s.indexOf( '=' ) ), s -> s.substring( s.indexOf( '=' ) + 1 ) + ) ) : Collections.emptyMap(); + parameters.put( "basedir", Objects.requireNonNull( getBasedir(), "basedir is null" ) ); + parameters.put( VelocityGenerator.VELOCITY_TEMPLATES, String.join( ",", templates ) ); + parameters.put( VelocityGenerator.VELOCITY_PARAMETERS, params ); + } + + protected boolean producesCompilableResult() + { + return true; + } + + public File getOutputDirectory() + { + return outputDirectory; + } + + public void setOutputDirectory( File outputDirectory ) + { + this.outputDirectory = outputDirectory; + } +} diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java new file mode 100644 index 000000000000..6f82631695ba --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java @@ -0,0 +1,166 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.runtime.RuntimeInstance; +import org.codehaus.modello.ModelloException; +import org.codehaus.modello.ModelloParameterConstants; +import org.codehaus.modello.model.Model; +import org.codehaus.modello.model.Version; +import org.codehaus.modello.plugin.AbstractModelloGenerator; +import org.codehaus.plexus.util.io.CachingWriter; + +public class VelocityGenerator + extends AbstractModelloGenerator +{ + public static final String VELOCITY_TEMPLATES = "modello.velocity.template"; + + public static final String VELOCITY_PARAMETERS = "modello.velocity.parameters"; + + @Override + public void generate( Model model, Properties parameters ) throws ModelloException + { + try + { + Map params = ( Map ) Objects.requireNonNull( parameters.get( VELOCITY_PARAMETERS ) ); + String templates = getParameter( parameters, VELOCITY_TEMPLATES ); + String output = getParameter( parameters, ModelloParameterConstants.OUTPUT_DIRECTORY ); + + Properties props = new Properties(); + props.put( "resource.loader.file.path", getParameter( parameters, "basedir" ) ); + RuntimeInstance velocity = new RuntimeInstance(); + velocity.init( props ); + + VelocityContext context = new VelocityContext(); + for ( Map.Entry prop : parameters.entrySet() ) + { + context.put( prop.getKey().toString(), prop.getValue() ); + } + for ( Map.Entry prop : params.entrySet() ) + { + context.put( prop.getKey(), prop.getValue() ); + } + Version version = new Version( getParameter( parameters, ModelloParameterConstants.VERSION ) ); + context.put( "version", version ); + context.put( "model", model ); + context.put( "Helper", new Helper( version ) ); + + for ( String templatePath : templates.split( "," ) ) + { + Template template = velocity.getTemplate( templatePath ); + + try ( Writer w = new RedirectingWriter( Paths.get( output ) ) ) + { + template.merge( context, w ); + } + } + } + catch ( Exception e ) + { + throw new ModelloException( "Unable to run velocity template", e ); + } + + } + + static class RedirectingWriter extends Writer + { + Path dir; + StringBuilder sb = new StringBuilder(); + Writer current; + + RedirectingWriter( Path dir ) + { + this.dir = dir; + } + + @Override + public void write( char[] cbuf, int off, int len ) throws IOException + { + for ( int i = 0; i < len; i++ ) + { + if ( cbuf[ off + i ] == '\n' ) + { + if ( sb.length() > 0 && sb.charAt( sb.length() - 1 ) == '\r' ) + { + sb.setLength( sb.length() - 1 ); + } + writeLine( sb.toString() ); + sb.setLength( 0 ); + } + else + { + sb.append( cbuf[ off + i ] ); + } + } + } + + protected void writeLine( String line ) throws IOException + { + if ( line.startsWith( "#MODELLO-VELOCITY#REDIRECT " ) ) + { + String file = line.substring( "#MODELLO-VELOCITY#REDIRECT ".length() ); + if ( current != null ) + { + current.close(); + } + Path out = dir.resolve( file ); + Files.createDirectories( out.getParent() ); + current = new CachingWriter( out, StandardCharsets.UTF_8 ); + } + else if ( current != null ) + { + current.write( line ); + current.write( "\n" ); + } + } + + @Override + public void flush() throws IOException + { + if ( current != null ) + { + current.flush(); + } + } + + @Override + public void close() throws IOException + { + if ( current != null ) + { + current.close(); + current = null; + } + } + } + +} diff --git a/api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml b/api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 000000000000..ed745b2fc461 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,31 @@ + + + + + + + + org.codehaus.modello.plugin.ModelloGenerator + velocity + org.codehaus.modello.plugin.velocity.VelocityGenerator + per-lookup + + + diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 000000000000..ce098702c367 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + + org.apache.maven + maven + 4.0.0-alpha-1-SNAPSHOT + + + maven-api + Maven API + pom + + + modello-plugin-velocity + maven-api-meta + maven-api-xml + maven-api-model + maven-api-settings + maven-api-toolchain + maven-api-core + + + diff --git a/build/checkstyle-suppressions.xml b/build/checkstyle-suppressions.xml index 78e9e3c05eeb..45702996fb5b 100644 --- a/build/checkstyle-suppressions.xml +++ b/build/checkstyle-suppressions.xml @@ -26,5 +26,4 @@ under the License. - diff --git a/maven-bom/pom.xml b/maven-bom/pom.xml index 4f9b6e370d3a..257eac644a4b 100644 --- a/maven-bom/pom.xml +++ b/maven-bom/pom.xml @@ -94,6 +94,11 @@ under the License. maven-model ${project.version} + + org.apache.maven + maven-api-core + ${project.version} + org.apache.maven maven-model-builder diff --git a/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java b/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java index 5f7957e7063e..2bfefbec4c0a 100644 --- a/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java +++ b/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java @@ -85,9 +85,9 @@ public AuthenticationInfo getAuthenticationInfo( String id ) { if ( id.equalsIgnoreCase( server.getId() ) ) { - SettingsDecryptionResult result = - settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( server ) ); - server = result.getServer(); + SettingsDecryptionResult result = settingsDecrypter.decrypt( + new DefaultSettingsDecryptionRequest( server.getDelegate() ) ); + server = new Server( result.getServer() ); AuthenticationInfo authInfo = new AuthenticationInfo(); authInfo.setUserName( server.getUsername() ); @@ -124,9 +124,9 @@ public ProxyInfo getProxy( String protocol ) { if ( proxy.isActive() && protocol.equalsIgnoreCase( proxy.getProtocol() ) ) { - SettingsDecryptionResult result = - settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( proxy ) ); - proxy = result.getProxy(); + SettingsDecryptionResult result = settingsDecrypter.decrypt( + new DefaultSettingsDecryptionRequest( proxy.getDelegate() ) ); + proxy = new Proxy( result.getProxy() ); ProxyInfo proxyInfo = new ProxyInfo(); proxyInfo.setHost( proxy.getHost() ); diff --git a/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java b/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java index 6b378b7af157..2c94f7a6f651 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java +++ b/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java @@ -19,19 +19,10 @@ * under the License. */ -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import org.apache.maven.model.Dependency; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.Repository; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** @deprecated */ @Deprecated @@ -54,309 +45,24 @@ public final class ModelUtils public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer, boolean handleAsInheritance ) { - if ( ( childContainer == null ) || ( parentContainer == null ) ) - { - // nothing to do. - return; - } - - List parentPlugins = parentContainer.getPlugins(); - - if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() ) - { - parentPlugins = new ArrayList<>( parentPlugins ); - - // If we're processing this merge as an inheritance, we have to build up a list of - // plugins that were considered for inheritance. - if ( handleAsInheritance ) - { - for ( Iterator it = parentPlugins.iterator(); it.hasNext(); ) - { - Plugin plugin = it.next(); - - String inherited = plugin.getInherited(); - - if ( ( inherited != null ) && !Boolean.parseBoolean( inherited ) ) - { - it.remove(); - } - } - } - - List assembledPlugins = new ArrayList<>(); - - Map childPlugins = childContainer.getPluginsAsMap(); - - for ( Plugin parentPlugin : parentPlugins ) - { - String parentInherited = parentPlugin.getInherited(); - - // only merge plugin definition from the parent if at least one - // of these is true: - // 1. we're not processing the plugins in an inheritance-based merge - // 2. the parent's flag is not set - // 3. the parent's flag is set to true - if ( !handleAsInheritance || ( parentInherited == null ) - || Boolean.parseBoolean( parentInherited ) ) - { - Plugin childPlugin = childPlugins.get( parentPlugin.getKey() ); - - if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) ) - { - mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance ); - - // fix for MNG-2221 (assembly cache was not being populated for later reference): - assembledPlugins.add( childPlugin ); - } - - // if we're processing this as an inheritance-based merge, and - // the parent's flag is not set, then we need to - // clear the inherited flag in the merge result. - if ( handleAsInheritance && ( parentInherited == null ) ) - { - parentPlugin.unsetInheritanceApplied(); - } - } - - // very important to use the parentPlugins List, rather than parentContainer.getPlugins() - // since this list is a local one, and may have been modified during processing. - List results = - ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins, childContainer.getPlugins() ); - - childContainer.setPlugins( results ); - - childContainer.flushPluginMap(); - } - } + throw new UnsupportedOperationException(); } public static List orderAfterMerge( List merged, List highPrioritySource, List lowPrioritySource ) { - List results = new ArrayList<>(); - - if ( !merged.isEmpty() ) - { - results.addAll( merged ); - } - - List missingFromResults = new ArrayList<>(); - - List> sources = new ArrayList<>(); - - sources.add( highPrioritySource ); - sources.add( lowPrioritySource ); - - for ( List source : sources ) - { - for ( Plugin item : source ) - { - if ( results.contains( item ) ) - { - if ( !missingFromResults.isEmpty() ) - { - int idx = results.indexOf( item ); - - if ( idx < 0 ) - { - idx = 0; - } - - results.addAll( idx, missingFromResults ); - - missingFromResults.clear(); - } - } - else - { - missingFromResults.add( item ); - } - } - - if ( !missingFromResults.isEmpty() ) - { - results.addAll( missingFromResults ); - - missingFromResults.clear(); - } - } - - return results; + throw new UnsupportedOperationException(); } public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance ) { - if ( ( child == null ) || ( parent == null ) ) - { - // nothing to do. - return; - } - - if ( parent.isExtensions() ) - { - child.setExtensions( true ); - } - - if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) ) - { - child.setVersion( parent.getVersion() ); - } - - Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); - Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); - - childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); - - child.setConfiguration( childConfiguration ); - - child.setDependencies( mergeDependencyList( child.getDependencies(), parent.getDependencies() ) ); - - // from here to the end of the method is dealing with merging of the section. - String parentInherited = parent.getInherited(); - - boolean parentIsInherited = ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ); - - List parentExecutions = parent.getExecutions(); - - if ( ( parentExecutions != null ) && !parentExecutions.isEmpty() ) - { - List mergedExecutions = new ArrayList<>(); - - Map assembledExecutions = new TreeMap<>(); - - Map childExecutions = child.getExecutionsAsMap(); - - for ( PluginExecution parentExecution : parentExecutions ) - { - String inherited = parentExecution.getInherited(); - - boolean parentExecInherited = - parentIsInherited && ( ( inherited == null ) || Boolean.parseBoolean( inherited ) ); - - if ( !handleAsInheritance || parentExecInherited ) - { - PluginExecution assembled = parentExecution; - - PluginExecution childExecution = childExecutions.get( parentExecution.getId() ); - - if ( childExecution != null ) - { - mergePluginExecutionDefinitions( childExecution, parentExecution ); - - assembled = childExecution; - } - else if ( handleAsInheritance && ( parentInherited == null ) ) - { - parentExecution.unsetInheritanceApplied(); - } - - assembledExecutions.put( assembled.getId(), assembled ); - mergedExecutions.add( assembled ); - } - } - - for ( PluginExecution childExecution : child.getExecutions() ) - { - if ( !assembledExecutions.containsKey( childExecution.getId() ) ) - { - mergedExecutions.add( childExecution ); - } - } - - child.setExecutions( mergedExecutions ); - - child.flushExecutionMap(); - } - - } - - private static void mergePluginExecutionDefinitions( PluginExecution child, PluginExecution parent ) - { - if ( child.getPhase() == null ) - { - child.setPhase( parent.getPhase() ); - } - - List parentGoals = parent.getGoals(); - List childGoals = child.getGoals(); - - List goals = new ArrayList<>(); - - if ( ( childGoals != null ) && !childGoals.isEmpty() ) - { - goals.addAll( childGoals ); - } - - if ( parentGoals != null ) - { - for ( String goal : parentGoals ) - { - if ( !goals.contains( goal ) ) - { - goals.add( goal ); - } - } - } - - child.setGoals( goals ); - - Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); - Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); - - childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); - - child.setConfiguration( childConfiguration ); - } - - public static List mergeRepositoryLists( List dominant, List recessive ) - { - - List repositories = new ArrayList<>( dominant ); - - for ( Repository repository : recessive ) - { - if ( !repositories.contains( repository ) ) - { - repositories.add( repository ); - } - } - - return repositories; + throw new UnsupportedOperationException(); } public static void mergeFilterLists( List childFilters, List parentFilters ) { - for ( String f : parentFilters ) - { - if ( !childFilters.contains( f ) ) - { - childFilters.add( f ); - } - } - } - - private static List mergeDependencyList( List child, List parent ) - { - Map depsMap = new LinkedHashMap<>(); - - if ( parent != null ) - { - for ( Dependency dependency : parent ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - if ( child != null ) - { - for ( Dependency dependency : child ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - return new ArrayList<>( depsMap.values() ); + throw new UnsupportedOperationException(); } } diff --git a/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java b/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java index 0113562cff29..b6dd90d81b91 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java +++ b/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java @@ -19,729 +19,38 @@ * under the License. */ -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.StringTokenizer; -import java.util.TreeMap; - import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.DeploymentRepository; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Extension; import org.apache.maven.model.Model; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; -import org.apache.maven.project.ModelUtils; import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * DefaultModelInheritanceAssembler */ @Component( role = ModelInheritanceAssembler.class ) public class DefaultModelInheritanceAssembler - implements ModelInheritanceAssembler + implements ModelInheritanceAssembler { - public void assembleBuildInheritance( Build childBuild, Build parentBuild, boolean handleAsInheritance ) - { - // The build has been set but we want to step in here and fill in - // values that have not been set by the child. - - if ( childBuild.getSourceDirectory() == null ) - { - childBuild.setSourceDirectory( parentBuild.getSourceDirectory() ); - } - - if ( childBuild.getScriptSourceDirectory() == null ) - { - childBuild.setScriptSourceDirectory( parentBuild.getScriptSourceDirectory() ); - } - - if ( childBuild.getTestSourceDirectory() == null ) - { - childBuild.setTestSourceDirectory( parentBuild.getTestSourceDirectory() ); - } - - if ( childBuild.getOutputDirectory() == null ) - { - childBuild.setOutputDirectory( parentBuild.getOutputDirectory() ); - } - - if ( childBuild.getTestOutputDirectory() == null ) - { - childBuild.setTestOutputDirectory( parentBuild.getTestOutputDirectory() ); - } - - // Extensions are accumulated - mergeExtensionLists( childBuild, parentBuild ); - - if ( childBuild.getDirectory() == null ) - { - childBuild.setDirectory( parentBuild.getDirectory() ); - } - - if ( childBuild.getDefaultGoal() == null ) - { - childBuild.setDefaultGoal( parentBuild.getDefaultGoal() ); - } - - if ( childBuild.getFinalName() == null ) - { - childBuild.setFinalName( parentBuild.getFinalName() ); - } - - ModelUtils.mergeFilterLists( childBuild.getFilters(), parentBuild.getFilters() ); - - List resources = childBuild.getResources(); - if ( ( resources == null ) || resources.isEmpty() ) - { - childBuild.setResources( parentBuild.getResources() ); - } - - resources = childBuild.getTestResources(); - if ( ( resources == null ) || resources.isEmpty() ) - { - childBuild.setTestResources( parentBuild.getTestResources() ); - } - - // Plugins are aggregated if Plugin.inherit != false - ModelUtils.mergePluginLists( childBuild, parentBuild, handleAsInheritance ); - - // Plugin management :: aggregate - PluginManagement dominantPM = childBuild.getPluginManagement(); - PluginManagement recessivePM = parentBuild.getPluginManagement(); - - if ( ( dominantPM == null ) && ( recessivePM != null ) ) - { - // FIXME: Filter out the inherited == false stuff! - childBuild.setPluginManagement( recessivePM ); - } - else - { - ModelUtils.mergePluginLists( childBuild.getPluginManagement(), parentBuild.getPluginManagement(), false ); - } - } - - private void assembleScmInheritance( Model child, Model parent, String childPathAdjustment, boolean appendPaths ) - { - if ( parent.getScm() != null ) - { - Scm parentScm = parent.getScm(); - - Scm childScm = child.getScm(); - - if ( childScm == null ) - { - childScm = new Scm(); - - child.setScm( childScm ); - } - - if ( StringUtils.isEmpty( childScm.getConnection() ) && !StringUtils.isEmpty( parentScm.getConnection() ) ) - { - childScm.setConnection( - appendPath( parentScm.getConnection(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - - if ( StringUtils.isEmpty( childScm.getDeveloperConnection() ) - && !StringUtils.isEmpty( parentScm.getDeveloperConnection() ) ) - { - childScm - .setDeveloperConnection( appendPath( parentScm.getDeveloperConnection(), child.getArtifactId(), - childPathAdjustment, appendPaths ) ); - } - - if ( StringUtils.isEmpty( childScm.getUrl() ) && !StringUtils.isEmpty( parentScm.getUrl() ) ) - { - childScm.setUrl( - appendPath( parentScm.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - } - } - - public void copyModel( Model dest, Model source ) - { - assembleModelInheritance( dest, source, null, false ); - } - + @Override public void assembleModelInheritance( Model child, Model parent, String childPathAdjustment ) { - assembleModelInheritance( child, parent, childPathAdjustment, true ); + throw new UnsupportedOperationException(); } + @Override public void assembleModelInheritance( Model child, Model parent ) { - assembleModelInheritance( child, parent, null, true ); - } - - private void assembleModelInheritance( Model child, Model parent, String childPathAdjustment, boolean appendPaths ) - { - // cannot inherit from null parent. - if ( parent == null ) - { - return; - } - - // Group id - if ( child.getGroupId() == null ) - { - child.setGroupId( parent.getGroupId() ); - } - - // version - if ( child.getVersion() == null ) - { - // The parent version may have resolved to something different, so we take what we asked for... - // instead of - child.setVersion( parent.getVersion() ); - - if ( child.getParent() != null ) - { - child.setVersion( child.getParent().getVersion() ); - } - } - - // inceptionYear - if ( child.getInceptionYear() == null ) - { - child.setInceptionYear( parent.getInceptionYear() ); - } - - // url - if ( child.getUrl() == null ) - { - if ( parent.getUrl() != null ) - { - child.setUrl( appendPath( parent.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - else - { - child.setUrl( parent.getUrl() ); - } - } - - assembleDistributionInheritance( child, parent, childPathAdjustment, appendPaths ); - - // issueManagement - if ( child.getIssueManagement() == null ) - { - child.setIssueManagement( parent.getIssueManagement() ); - } - - // description - if ( child.getDescription() == null ) - { - child.setDescription( parent.getDescription() ); - } - - // Organization - if ( child.getOrganization() == null ) - { - child.setOrganization( parent.getOrganization() ); - } - - // Scm - assembleScmInheritance( child, parent, childPathAdjustment, appendPaths ); - - // ciManagement - if ( child.getCiManagement() == null ) - { - child.setCiManagement( parent.getCiManagement() ); - } - - // developers - if ( child.getDevelopers().size() == 0 ) - { - child.setDevelopers( parent.getDevelopers() ); - } - - // licenses - if ( child.getLicenses().size() == 0 ) - { - child.setLicenses( parent.getLicenses() ); - } - - // developers - if ( child.getContributors().size() == 0 ) - { - child.setContributors( parent.getContributors() ); - } - - // mailingLists - if ( child.getMailingLists().size() == 0 ) - { - child.setMailingLists( parent.getMailingLists() ); - } - - // Build - assembleBuildInheritance( child, parent ); - - assembleDependencyInheritance( child, parent ); - - child.setRepositories( ModelUtils.mergeRepositoryLists( child.getRepositories(), parent.getRepositories() ) ); -// child.setPluginRepositories( -// ModelUtils.mergeRepositoryLists( child.getPluginRepositories(), parent.getPluginRepositories() ) ); - - assembleReportingInheritance( child, parent ); - - assembleDependencyManagementInheritance( child, parent ); - - Properties props = new Properties(); - props.putAll( parent.getProperties() ); - props.putAll( child.getProperties() ); - - child.setProperties( props ); - } - - private void assembleDependencyManagementInheritance( Model child, Model parent ) - { - DependencyManagement parentDepMgmt = parent.getDependencyManagement(); - - DependencyManagement childDepMgmt = child.getDependencyManagement(); - - if ( parentDepMgmt != null ) - { - if ( childDepMgmt == null ) - { - child.setDependencyManagement( parentDepMgmt ); - } - else - { - List childDeps = childDepMgmt.getDependencies(); - - Map mappedChildDeps = new TreeMap<>(); - for ( Dependency dep : childDeps ) - { - mappedChildDeps.put( dep.getManagementKey(), dep ); - } - - for ( Dependency dep : parentDepMgmt.getDependencies() ) - { - if ( !mappedChildDeps.containsKey( dep.getManagementKey() ) ) - { - childDepMgmt.addDependency( dep ); - } - } - } - } - } - - private void assembleReportingInheritance( Model child, Model parent ) - { - // Reports :: aggregate - Reporting childReporting = child.getReporting(); - Reporting parentReporting = parent.getReporting(); - - if ( parentReporting != null ) - { - if ( childReporting == null ) - { - childReporting = new Reporting(); - child.setReporting( childReporting ); - } - - childReporting.setExcludeDefaults( parentReporting.isExcludeDefaults() ); - - if ( StringUtils.isEmpty( childReporting.getOutputDirectory() ) ) - { - childReporting.setOutputDirectory( parentReporting.getOutputDirectory() ); - } - - mergeReportPluginLists( childReporting, parentReporting, true ); - } - } - - private static void mergeReportPluginLists( Reporting child, Reporting parent, boolean handleAsInheritance ) - { - if ( ( child == null ) || ( parent == null ) ) - { - // nothing to do. - return; - } - - List parentPlugins = parent.getPlugins(); - - if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() ) - { - Map assembledPlugins = new TreeMap<>(); - - Map childPlugins = child.getReportPluginsAsMap(); - - for ( ReportPlugin parentPlugin : parentPlugins ) - { - String parentInherited = parentPlugin.getInherited(); - - if ( !handleAsInheritance || ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ) ) - { - - ReportPlugin assembledPlugin = parentPlugin; - - ReportPlugin childPlugin = childPlugins.get( parentPlugin.getKey() ); - - if ( childPlugin != null ) - { - assembledPlugin = childPlugin; - - mergeReportPluginDefinitions( childPlugin, parentPlugin, handleAsInheritance ); - } - - if ( handleAsInheritance && ( parentInherited == null ) ) - { - assembledPlugin.unsetInheritanceApplied(); - } - - assembledPlugins.put( assembledPlugin.getKey(), assembledPlugin ); - } - } - - for ( ReportPlugin childPlugin : childPlugins.values() ) - { - if ( !assembledPlugins.containsKey( childPlugin.getKey() ) ) - { - assembledPlugins.put( childPlugin.getKey(), childPlugin ); - } - } - - child.setPlugins( new ArrayList<>( assembledPlugins.values() ) ); - - child.flushReportPluginMap(); - } - } - - private static void mergeReportSetDefinitions( ReportSet child, ReportSet parent ) - { - List parentReports = parent.getReports(); - List childReports = child.getReports(); - - List reports = new ArrayList<>(); - - if ( ( childReports != null ) && !childReports.isEmpty() ) - { - reports.addAll( childReports ); - } - - if ( parentReports != null ) - { - for ( String report : parentReports ) - { - if ( !reports.contains( report ) ) - { - reports.add( report ); - } - } - } - - child.setReports( reports ); - - Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); - Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); - - childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); - - child.setConfiguration( childConfiguration ); - } - - - public static void mergeReportPluginDefinitions( ReportPlugin child, ReportPlugin parent, - boolean handleAsInheritance ) - { - if ( ( child == null ) || ( parent == null ) ) - { - // nothing to do. - return; - } - - if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) ) - { - child.setVersion( parent.getVersion() ); - } - - // from here to the end of the method is dealing with merging of the section. - String parentInherited = parent.getInherited(); - - boolean parentIsInherited = ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ); - - List parentReportSets = parent.getReportSets(); - - if ( ( parentReportSets != null ) && !parentReportSets.isEmpty() ) - { - Map assembledReportSets = new TreeMap<>(); - - Map childReportSets = child.getReportSetsAsMap(); - - for ( Object parentReportSet1 : parentReportSets ) - { - ReportSet parentReportSet = (ReportSet) parentReportSet1; - - if ( !handleAsInheritance || parentIsInherited ) - { - ReportSet assembledReportSet = parentReportSet; - - ReportSet childReportSet = childReportSets.get( parentReportSet.getId() ); - - if ( childReportSet != null ) - { - mergeReportSetDefinitions( childReportSet, parentReportSet ); - - assembledReportSet = childReportSet; - } - else if ( handleAsInheritance && ( parentInherited == null ) ) - { - parentReportSet.unsetInheritanceApplied(); - } - - assembledReportSets.put( assembledReportSet.getId(), assembledReportSet ); - } - } - - for ( Map.Entry entry : childReportSets.entrySet() ) - { - String id = entry.getKey(); - - if ( !assembledReportSets.containsKey( id ) ) - { - assembledReportSets.put( id, entry.getValue() ); - } - } - - child.setReportSets( new ArrayList<>( assembledReportSets.values() ) ); - - child.flushReportSetMap(); - } - - } - - private void assembleDependencyInheritance( Model child, Model parent ) - { - Map depsMap = new LinkedHashMap<>(); - - List deps = parent.getDependencies(); - - if ( deps != null ) - { - for ( Dependency dependency : deps ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - deps = child.getDependencies(); - - if ( deps != null ) - { - for ( Dependency dependency : deps ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - child.setDependencies( new ArrayList<>( depsMap.values() ) ); - } - - private void assembleBuildInheritance( Model child, Model parent ) - { - Build childBuild = child.getBuild(); - Build parentBuild = parent.getBuild(); - - if ( parentBuild != null ) - { - if ( childBuild == null ) - { - childBuild = new Build(); - child.setBuild( childBuild ); - } - - assembleBuildInheritance( childBuild, parentBuild, true ); - } - } - - private void assembleDistributionInheritance( Model child, Model parent, String childPathAdjustment, - boolean appendPaths ) - { - if ( parent.getDistributionManagement() != null ) - { - DistributionManagement parentDistMgmt = parent.getDistributionManagement(); - - DistributionManagement childDistMgmt = child.getDistributionManagement(); - - if ( childDistMgmt == null ) - { - childDistMgmt = new DistributionManagement(); - - child.setDistributionManagement( childDistMgmt ); - } - - if ( childDistMgmt.getSite() == null ) - { - if ( parentDistMgmt.getSite() != null ) - { - Site site = new Site(); - - childDistMgmt.setSite( site ); - - site.setId( parentDistMgmt.getSite().getId() ); - - site.setName( parentDistMgmt.getSite().getName() ); - - site.setUrl( parentDistMgmt.getSite().getUrl() ); - - if ( site.getUrl() != null ) - { - site.setUrl( - appendPath( site.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - } - } - - if ( childDistMgmt.getRepository() == null ) - { - if ( parentDistMgmt.getRepository() != null ) - { - DeploymentRepository repository = copyDistributionRepository( parentDistMgmt.getRepository() ); - childDistMgmt.setRepository( repository ); - } - } - - if ( childDistMgmt.getSnapshotRepository() == null ) - { - if ( parentDistMgmt.getSnapshotRepository() != null ) - { - DeploymentRepository repository = - copyDistributionRepository( parentDistMgmt.getSnapshotRepository() ); - childDistMgmt.setSnapshotRepository( repository ); - } - } - - if ( StringUtils.isEmpty( childDistMgmt.getDownloadUrl() ) ) - { - childDistMgmt.setDownloadUrl( parentDistMgmt.getDownloadUrl() ); - } - - // NOTE: We SHOULD NOT be inheriting status, since this is an assessment of the POM quality. - // NOTE: We SHOULD NOT be inheriting relocation, since this relates to a single POM - } - } - - private static DeploymentRepository copyDistributionRepository( DeploymentRepository parentRepository ) - { - DeploymentRepository repository = new DeploymentRepository(); - - repository.setId( parentRepository.getId() ); - - repository.setName( parentRepository.getName() ); - - repository.setUrl( parentRepository.getUrl() ); - - repository.setLayout( parentRepository.getLayout() ); - - repository.setUniqueVersion( parentRepository.isUniqueVersion() ); - - return repository; - } - - // TODO This should eventually be migrated to DefaultPathTranslator. - protected String appendPath( String parentPath, String childPath, String pathAdjustment, boolean appendPaths ) - { - String uncleanPath = parentPath; - - if ( appendPaths ) - { - if ( pathAdjustment != null ) - { - uncleanPath += "/" + pathAdjustment; - } - - if ( childPath != null ) - { - uncleanPath += "/" + childPath; - } - } - - String cleanedPath = ""; - - int protocolIdx = uncleanPath.indexOf( "://" ); - - if ( protocolIdx > -1 ) - { - cleanedPath = uncleanPath.substring( 0, protocolIdx + 3 ); - uncleanPath = uncleanPath.substring( protocolIdx + 3 ); - } - - if ( uncleanPath.startsWith( "/" ) ) - { - cleanedPath += "/"; - } - - return cleanedPath + resolvePath( uncleanPath ); + throw new UnsupportedOperationException(); } - // TODO Move this to plexus-utils' PathTool. - private static String resolvePath( String uncleanPath ) + @Override + public void assembleBuildInheritance( Build childBuild, Build parentBuild, boolean handleAsInheritance ) { - LinkedList pathElements = new LinkedList<>(); - - StringTokenizer tokenizer = new StringTokenizer( uncleanPath, "/" ); - - while ( tokenizer.hasMoreTokens() ) - { - String token = tokenizer.nextToken(); - - switch ( token ) - { - case "": - // Empty path entry ("...//.."), remove. - break; - case "..": - if ( pathElements.isEmpty() ) - { - // FIXME: somehow report to the user - // that there are too many '..' elements. - // For now, ignore the extra '..'. - } - else - { - pathElements.removeLast(); - } - break; - default: - pathElements.addLast( token ); - break; - } - } - - StringBuilder cleanedPath = new StringBuilder(); - - while ( !pathElements.isEmpty() ) - { - cleanedPath.append( pathElements.removeFirst() ); - if ( !pathElements.isEmpty() ) - { - cleanedPath.append( '/' ); - } - } - - return cleanedPath.toString(); + throw new UnsupportedOperationException(); } - private static void mergeExtensionLists( Build childBuild, Build parentBuild ) + @Override + public void copyModel( Model dest, Model source ) { - for ( Extension e : parentBuild.getExtensions() ) - { - if ( !childBuild.getExtensions().contains( e ) ) - { - childBuild.addExtension( e ); - } - } + throw new UnsupportedOperationException(); } -} +} \ No newline at end of file diff --git a/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java b/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java index 8dc8784b12e6..71da2ed3b00c 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java +++ b/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java @@ -343,7 +343,8 @@ else if ( Map.class.isAssignableFrom( type ) ) private boolean isQualifiedForInterpolation( Class cls ) { - return !cls.getPackage().getName().startsWith( "java" ); + return !cls.getPackage().getName().startsWith( "java" ) + && !cls.getPackage().getName().startsWith( "sun.nio.fs" ); } private boolean isQualifiedForInterpolation( Field field, Class fieldType ) diff --git a/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java b/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java index a89ea37cd949..bd97b399284d 100644 --- a/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java +++ b/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java @@ -84,7 +84,7 @@ */ @Component( role = RepositorySystem.class, hint = "default" ) public class LegacyRepositorySystem - implements RepositorySystem + implements RepositorySystem { @Requirement @@ -146,13 +146,13 @@ public Artifact createDependencyArtifact( Dependency d ) { // MNG-5368: Log a message instead of returning 'null' silently. this.logger.error( String.format( "Invalid version specification '%s' creating dependency artifact '%s'.", - d.getVersion(), d ), e ); + d.getVersion(), d ), e ); return null; } Artifact artifact = - artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(), - d.getClassifier(), d.getScope(), d.isOptional() ); + artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(), + d.getClassifier(), d.getScope(), d.isOptional() ); if ( Artifact.SCOPE_SYSTEM.equals( d.getScope() ) && d.getSystemPath() != null ) { @@ -185,8 +185,8 @@ public Artifact createExtensionArtifact( String groupId, String artifactId, Stri { // MNG-5368: Log a message instead of returning 'null' silently. this.logger.error( String.format( - "Invalid version specification '%s' creating extension artifact '%s:%s:%s'.", - version, groupId, artifactId, version ), e ); + "Invalid version specification '%s' creating extension artifact '%s:%s:%s'.", + version, groupId, artifactId, version ), e ); return null; } @@ -216,8 +216,8 @@ public Artifact createPluginArtifact( Plugin plugin ) { // MNG-5368: Log a message instead of returning 'null' silently. this.logger.error( String.format( - "Invalid version specification '%s' creating plugin artifact '%s'.", - version, plugin ), e ); + "Invalid version specification '%s' creating plugin artifact '%s'.", + version, plugin ), e ); return null; } @@ -251,41 +251,41 @@ public ArtifactRepositoryPolicy buildArtifactRepositoryPolicy( RepositoryPolicy } public ArtifactRepository createDefaultLocalRepository() - throws InvalidRepositoryException + throws InvalidRepositoryException { return createLocalRepository( RepositorySystem.defaultUserLocalRepository ); } public ArtifactRepository createLocalRepository( File localRepository ) - throws InvalidRepositoryException + throws InvalidRepositoryException { return createRepository( "file://" + localRepository.toURI().getRawPath(), - RepositorySystem.DEFAULT_LOCAL_REPO_ID, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, - ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); + RepositorySystem.DEFAULT_LOCAL_REPO_ID, true, + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, + ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); } public ArtifactRepository createDefaultRemoteRepository() - throws InvalidRepositoryException + throws InvalidRepositoryException { return createRepository( RepositorySystem.DEFAULT_REMOTE_REPO_URL, RepositorySystem.DEFAULT_REMOTE_REPO_ID, - true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, false, - ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, - ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN ); + true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, false, + ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, + ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN ); } public ArtifactRepository createLocalRepository( String url, String repositoryId ) - throws IOException + throws IOException { return createRepository( canonicalFileUrl( url ), repositoryId, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, - ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, + ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); } private String canonicalFileUrl( String url ) - throws IOException + throws IOException { if ( !url.startsWith( "file:" ) ) { @@ -322,12 +322,12 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) try { LocalArtifactRepository ideWorkspace = - plexus.lookup( LocalArtifactRepository.class, LocalArtifactRepository.IDE_WORKSPACE ); + plexus.lookup( LocalArtifactRepository.class, LocalArtifactRepository.IDE_WORKSPACE ); if ( request.getLocalRepository() instanceof DelegatingLocalArtifactRepository ) { DelegatingLocalArtifactRepository delegatingLocalRepository = - (DelegatingLocalArtifactRepository) request.getLocalRepository(); + (DelegatingLocalArtifactRepository) request.getLocalRepository(); LocalArtifactRepository orig = delegatingLocalRepository.getIdeWorkspace(); @@ -346,7 +346,7 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) { ArtifactRepository localRepository = request.getLocalRepository(); DelegatingLocalArtifactRepository delegatingLocalRepository = - new DelegatingLocalArtifactRepository( localRepository ); + new DelegatingLocalArtifactRepository( localRepository ); delegatingLocalRepository.setIdeWorkspace( ideWorkspace ); request.setLocalRepository( delegatingLocalRepository ); try @@ -367,21 +367,21 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) return artifactResolver.resolve( request ); } -// public void addProxy( String protocol, String host, int port, String username, String password, -// String nonProxyHosts ) -// { -// ProxyInfo proxyInfo = new ProxyInfo(); -// proxyInfo.setHost( host ); -// proxyInfo.setType( protocol ); -// proxyInfo.setPort( port ); -// proxyInfo.setNonProxyHosts( nonProxyHosts ); -// proxyInfo.setUserName( username ); -// proxyInfo.setPassword( password ); -// -// proxies.put( protocol, proxyInfo ); -// -// wagonManager.addProxy( protocol, host, port, username, password, nonProxyHosts ); -// } + // public void addProxy( String protocol, String host, int port, String username, String password, + // String nonProxyHosts ) + // { + // ProxyInfo proxyInfo = new ProxyInfo(); + // proxyInfo.setHost( host ); + // proxyInfo.setType( protocol ); + // proxyInfo.setPort( port ); + // proxyInfo.setNonProxyHosts( nonProxyHosts ); + // proxyInfo.setUserName( username ); + // proxyInfo.setPassword( password ); + // + // proxies.put( protocol, proxyInfo ); + // + // wagonManager.addProxy( protocol, host, port, username, password, nonProxyHosts ); + // } public List getEffectiveRepositories( List repositories ) { @@ -408,7 +408,7 @@ public List getEffectiveRepositories( List mirroredRepos = new ArrayList<>(); List releasePolicies = - new ArrayList<>( aliasedRepos.size() ); + new ArrayList<>( aliasedRepos.size() ); for ( ArtifactRepository aliasedRepo : aliasedRepos ) { @@ -419,7 +419,7 @@ public List getEffectiveRepositories( List snapshotPolicies = - new ArrayList<>( aliasedRepos.size() ); + new ArrayList<>( aliasedRepos.size() ); for ( ArtifactRepository aliasedRepo : aliasedRepos ) { @@ -431,8 +431,8 @@ public List getEffectiveRepositories( List repositories, List repositories, List - * Given: - *

- *
-     *   parent: X -> A -> B -> D -> E
-     *   child: Y -> A -> C -> D -> F
-     * 
- *

- * Result: - *

- *
-     *   X -> Y -> A -> B -> C -> D -> E -> F
-     * 
- */ - @Test - public void testShouldPreserveChildOrderingOfPluginsAfterParentMerge() - { - PluginContainer parent = new PluginContainer(); - - parent.addPlugin( createPlugin( "group", "artifact", "1.0", Collections.EMPTY_MAP ) ); - parent.addPlugin( createPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key", "value" ) ) ); - - PluginContainer child = new PluginContainer(); - - child.addPlugin( createPlugin( "group3", "artifact3", "1.0", Collections.EMPTY_MAP ) ); - child.addPlugin( createPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key2", "value2" ) ) ); - - ModelUtils.mergePluginLists( child, parent, true ); - - List results = child.getPlugins(); - - assertEquals( 3, results.size() ); - - Plugin result1 = (Plugin) results.get( 0 ); - - assertEquals( "group", result1.getGroupId() ); - assertEquals( "artifact", result1.getArtifactId() ); - - Plugin result2 = (Plugin) results.get( 1 ); - - assertEquals( "group3", result2.getGroupId() ); - assertEquals( "artifact3", result2.getArtifactId() ); - - Plugin result3 = (Plugin) results.get( 2 ); - - assertEquals( "group2", result3.getGroupId() ); - assertEquals( "artifact2", result3.getArtifactId() ); - - Xpp3Dom result3Config = (Xpp3Dom) result3.getConfiguration(); - - assertNotNull( result3Config ); - - assertEquals( "value", result3Config.getChild( "key" ).getValue() ); - assertEquals( "value2", result3Config.getChild( "key2" ).getValue() ); - } - - private Plugin createPlugin( String groupId, String artifactId, String version, Map configuration ) - { - Plugin plugin = new Plugin(); - plugin.setGroupId( groupId ); - plugin.setArtifactId( artifactId ); - plugin.setVersion( version ); - - Xpp3Dom config = new Xpp3Dom( "configuration" ); - - if( configuration != null ) - { - for ( Object o : configuration.entrySet() ) - { - Map.Entry entry = (Map.Entry) o; - - Xpp3Dom param = new Xpp3Dom( String.valueOf( entry.getKey() ) ); - param.setValue( String.valueOf( entry.getValue() ) ); - - config.addChild( param ); - } - } - - plugin.setConfiguration( config ); - - return plugin; - } - - @Test - public void testShouldInheritOnePluginWithExecution() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - ModelUtils.mergePluginDefinitions( child, parent, false ); - - assertEquals( 1, child.getExecutions().size() ); - } - - @Test - public void testShouldMergeInheritedPluginHavingExecutionWithLocalPlugin() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - PluginExecution childExecution = new PluginExecution(); - childExecution.setId( "testExecution2" ); - - child.addExecution( childExecution ); - - ModelUtils.mergePluginDefinitions( child, parent, false ); - - assertEquals( 2, child.getExecutions().size() ); - } - - @Test - public void testShouldMergeOnePluginWithInheritExecutionWithoutDuplicatingPluginInList() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Build parentContainer = new Build(); - parentContainer.addPlugin( parent ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - Build childContainer = new Build(); - childContainer.addPlugin( child ); - - ModelUtils.mergePluginLists( childContainer, parentContainer, true ); - - List plugins = childContainer.getPlugins(); - - assertEquals( 1, plugins.size() ); - - Plugin plugin = (Plugin) plugins.get( 0 ); - - assertEquals( 1, plugin.getExecutions().size() ); - } - - @Test - public void testShouldMergePluginWithDifferentExecutionFromParentWithoutDuplicatingPluginInList() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Build parentContainer = new Build(); - parentContainer.addPlugin( parent ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - PluginExecution childExecution = new PluginExecution(); - childExecution.setId( "testExecution2" ); - - child.addExecution( childExecution ); - - - Build childContainer = new Build(); - childContainer.addPlugin( child ); - - ModelUtils.mergePluginLists( childContainer, parentContainer, true ); - - List plugins = childContainer.getPlugins(); - - assertEquals( 1, plugins.size() ); - - Plugin plugin = (Plugin) plugins.get( 0 ); - - assertEquals( 2, plugin.getExecutions().size() ); - } - - @Test - public void testShouldNOTMergeInheritedPluginHavingInheritEqualFalse() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - parent.setInherited( "false" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - ModelUtils.mergePluginDefinitions( child, parent, true ); - - assertEquals( 0, child.getExecutions().size() ); - } - - /** - * Verifies MNG-1499: The order of the merged list should be the plugins specified by the parent followed by the - * child list. - */ - @Test - public void testShouldKeepOriginalPluginOrdering() - { - Plugin parentPlugin1 = new Plugin(); - parentPlugin1.setArtifactId( "testArtifact" ); - parentPlugin1.setGroupId( "zzz" ); // This will put this plugin last in the sorted map - parentPlugin1.setVersion( "1.0" ); - - PluginExecution parentExecution1 = new PluginExecution(); - parentExecution1.setId( "testExecution" ); - - parentPlugin1.addExecution( parentExecution1 ); - - Plugin parentPlugin2 = new Plugin(); - parentPlugin2.setArtifactId( "testArtifact" ); - parentPlugin2.setGroupId( "yyy" ); - parentPlugin2.setVersion( "1.0" ); - - PluginExecution parentExecution2 = new PluginExecution(); - parentExecution2.setId( "testExecution" ); - - parentPlugin2.addExecution( parentExecution2 ); - - PluginContainer parentContainer = new PluginContainer(); - parentContainer.addPlugin(parentPlugin1); - parentContainer.addPlugin(parentPlugin2); - - - Plugin childPlugin1 = new Plugin(); - childPlugin1.setArtifactId( "testArtifact" ); - childPlugin1.setGroupId( "bbb" ); - childPlugin1.setVersion( "1.0" ); - - PluginExecution childExecution1 = new PluginExecution(); - childExecution1.setId( "testExecution" ); - - childPlugin1.addExecution( childExecution1 ); - - Plugin childPlugin2 = new Plugin(); - childPlugin2.setArtifactId( "testArtifact" ); - childPlugin2.setGroupId( "aaa" ); - childPlugin2.setVersion( "1.0" ); - - PluginExecution childExecution2 = new PluginExecution(); - childExecution2.setId( "testExecution" ); - - childPlugin2.addExecution( childExecution2 ); - - PluginContainer childContainer = new PluginContainer(); - childContainer.addPlugin(childPlugin1); - childContainer.addPlugin(childPlugin2); - - - ModelUtils.mergePluginLists(childContainer, parentContainer, true); - - assertEquals( 4, childContainer.getPlugins().size() ); - assertSame(parentPlugin1, childContainer.getPlugins().get(0)); - assertSame(parentPlugin2, childContainer.getPlugins().get(1)); - assertSame(childPlugin1, childContainer.getPlugins().get(2)); - assertSame(childPlugin2, childContainer.getPlugins().get(3)); - } - - /** - * Verifies MNG-1499: The ordering of plugin executions should also be in the specified order. - */ - @Test - public void testShouldKeepOriginalPluginExecutionOrdering() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution1 = new PluginExecution(); - parentExecution1.setId( "zzz" ); // Will show up last in the sorted map - PluginExecution parentExecution2 = new PluginExecution(); - parentExecution2.setId( "yyy" ); // Will show up last in the sorted map - - parent.addExecution( parentExecution1 ); - parent.addExecution( parentExecution2 ); - - // this block verifies MNG-1703 - Dependency dep = new Dependency(); - dep.setGroupId( "depGroupId" ); - dep.setArtifactId( "depArtifactId" ); - dep.setVersion( "depVersion" ); - parent.setDependencies( Collections.singletonList( dep ) ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - PluginExecution childExecution1 = new PluginExecution(); - childExecution1.setId( "bbb" ); - PluginExecution childExecution2 = new PluginExecution(); - childExecution2.setId( "aaa" ); - - child.addExecution( childExecution1 ); - child.addExecution( childExecution2 ); - - ModelUtils.mergePluginDefinitions( child, parent, false ); - - assertEquals( 4, child.getExecutions().size() ); - assertSame(parentExecution1, child.getExecutions().get(0)); - assertSame(parentExecution2, child.getExecutions().get(1)); - assertSame(childExecution1, child.getExecutions().get(2)); - assertSame(childExecution2, child.getExecutions().get(3)); - - // this block prevents MNG-1703 - assertEquals( 1, child.getDependencies().size() ); - Dependency dep2 = child.getDependencies().get( 0 ); - assertEquals( dep.getManagementKey(), dep2.getManagementKey() ); - } - - @Test - public void testShouldOverwritePluginConfigurationSubItemsByDefault() - throws XmlPullParserException, IOException - { - String parentConfigStr = "onetwo"; - Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) ); - - Plugin parentPlugin = createPlugin( "group", "artifact", "1", null ); - parentPlugin.setConfiguration( parentConfig ); - - String childConfigStr = "three"; - Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) ); - - Plugin childPlugin = createPlugin( "group", "artifact", "1", null ); - childPlugin.setConfiguration( childConfig ); - - ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, true ); - - Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration(); - Xpp3Dom items = result.getChild( "items" ); - - assertEquals( 1, items.getChildCount() ); - - Xpp3Dom item = items.getChild( 0 ); - assertEquals( "three", item.getValue() ); - } - - @Test - public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet() - throws XmlPullParserException, IOException - { - String parentConfigStr = "onetwo"; - Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) ); - - Plugin parentPlugin = createPlugin( "group", "artifact", "1", null ); - parentPlugin.setConfiguration( parentConfig ); - - String childConfigStr = "three"; - Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) ); - - Plugin childPlugin = createPlugin( "group", "artifact", "1", null ); - childPlugin.setConfiguration( childConfig ); - - ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, true ); - - Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration(); - Xpp3Dom items = result.getChild( "items" ); - - assertEquals( 3, items.getChildCount() ); - - Xpp3Dom[] item = items.getChildren(); - - List actual = Arrays.asList( item[0].getValue(), item[1].getValue(), item[2].getValue() ); - List expected = Arrays.asList( "one", "two", "three" ); - Collections.sort( actual ); - Collections.sort( expected ); - assertEquals( expected, actual ); - } - - @Test - public void testShouldNotMergePluginExecutionWhenExecInheritedIsFalseAndTreatAsInheritanceIsTrue() - { - String gid = "group"; - String aid = "artifact"; - String ver = "1"; - - PluginContainer parent = new PluginContainer(); - Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - - pParent.setInherited( Boolean.toString( true ) ); - - PluginExecution eParent = new PluginExecution(); - - String testId = "test"; - - eParent.setId( testId ); - eParent.addGoal( "run" ); - eParent.setPhase( "initialize" ); - eParent.setInherited( Boolean.toString( false ) ); - - pParent.addExecution( eParent ); - parent.addPlugin( pParent ); - - PluginContainer child = new PluginContainer(); - Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - PluginExecution eChild = new PluginExecution(); - - eChild.setId( "child-specified" ); - eChild.addGoal( "child" ); - eChild.setPhase( "compile" ); - - pChild.addExecution( eChild ); - child.addPlugin( pChild ); - - ModelUtils.mergePluginDefinitions( pChild, pParent, true ); - - Map executionMap = pChild.getExecutionsAsMap(); - assertNull( executionMap.get( testId ), "test execution should not be inherited from parent." ); - } - - @Test - public void testShouldNotMergePluginExecutionWhenPluginInheritedIsFalseAndTreatAsInheritanceIsTrue() - { - String gid = "group"; - String aid = "artifact"; - String ver = "1"; - - PluginContainer parent = new PluginContainer(); - Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - - pParent.setInherited( Boolean.toString( false ) ); - - PluginExecution eParent = new PluginExecution(); - - String testId = "test"; - - eParent.setId( testId ); - eParent.addGoal( "run" ); - eParent.setPhase( "initialize" ); - eParent.setInherited( Boolean.toString( true ) ); - - pParent.addExecution( eParent ); - parent.addPlugin( pParent ); - - PluginContainer child = new PluginContainer(); - Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - PluginExecution eChild = new PluginExecution(); - - eChild.setId( "child-specified" ); - eChild.addGoal( "child" ); - eChild.setPhase( "compile" ); - - pChild.addExecution( eChild ); - child.addPlugin( pChild ); - - ModelUtils.mergePluginDefinitions( pChild, pParent, true ); - - Map executionMap = pChild.getExecutionsAsMap(); - assertNull( executionMap.get( testId ), "test execution should not be inherited from parent." ); - } - - @Test - public void testShouldMergePluginExecutionWhenExecInheritedIsTrueAndTreatAsInheritanceIsTrue() - { - String gid = "group"; - String aid = "artifact"; - String ver = "1"; - - PluginContainer parent = new PluginContainer(); - Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - - pParent.setInherited( Boolean.toString( true ) ); - - PluginExecution eParent = new PluginExecution(); - - String testId = "test"; - - eParent.setId( testId ); - eParent.addGoal( "run" ); - eParent.setPhase( "initialize" ); - eParent.setInherited( Boolean.toString( true ) ); - - pParent.addExecution( eParent ); - parent.addPlugin( pParent ); - - PluginContainer child = new PluginContainer(); - Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - PluginExecution eChild = new PluginExecution(); - - eChild.setId( "child-specified" ); - eChild.addGoal( "child" ); - eChild.setPhase( "compile" ); - - pChild.addExecution( eChild ); - child.addPlugin( pChild ); - - ModelUtils.mergePluginDefinitions( pChild, pParent, true ); - - Map executionMap = pChild.getExecutionsAsMap(); - assertNotNull( executionMap.get( testId ), "test execution should be inherited from parent." ); - } - -} diff --git a/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java b/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java index 50f5f0894192..25adce840283 100644 --- a/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java +++ b/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java @@ -21,8 +21,10 @@ import java.io.File; import java.util.Map; +import java.util.stream.Collectors; import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginExecution; import org.apache.maven.project.MavenProject; import org.apache.maven.project.inheritance.AbstractProjectInheritanceTestCase; import org.junit.jupiter.api.Test; diff --git a/maven-core/pom.xml b/maven-core/pom.xml index 8455f8eb6c6b..143175f4b429 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -81,6 +81,10 @@ under the License. org.apache.maven maven-resolver-provider
+ + org.apache.maven + maven-api-core + org.apache.maven.resolver maven-resolver-impl diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index 9792c219c340..068b1e696ca7 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Session; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.execution.BuildResumptionAnalyzer; import org.apache.maven.execution.BuildResumptionDataRepository; @@ -34,13 +35,14 @@ import org.apache.maven.graph.GraphBuilder; import org.apache.maven.graph.ProjectSelector; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; +import org.apache.maven.internal.impl.DefaultSessionFactory; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.internal.aether.MavenChainedWorkspaceReader; import org.apache.maven.lifecycle.internal.ExecutionEventCatapult; import org.apache.maven.lifecycle.internal.LifecycleStarter; -import org.apache.maven.model.Model; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Prerequisites; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblem; import org.apache.maven.model.building.Result; import org.apache.maven.model.superpom.SuperPomProvider; @@ -110,9 +112,12 @@ public class DefaultMaven private final SuperPomProvider superPomProvider; + private final DefaultSessionFactory defaultSessionFactory; + private final ProjectSelector projectSelector; @Inject + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultMaven( ProjectBuilder projectBuilder, LifecycleStarter lifecycleStarter, @@ -124,7 +129,8 @@ public DefaultMaven( @Named( GraphBuilder.HINT ) GraphBuilder graphBuilder, BuildResumptionAnalyzer buildResumptionAnalyzer, BuildResumptionDataRepository buildResumptionDataRepository, - SuperPomProvider superPomProvider ) + SuperPomProvider superPomProvider, + DefaultSessionFactory defaultSessionFactory ) { this.projectBuilder = projectBuilder; this.lifecycleStarter = lifecycleStarter; @@ -137,6 +143,7 @@ public DefaultMaven( this.buildResumptionAnalyzer = buildResumptionAnalyzer; this.buildResumptionDataRepository = buildResumptionDataRepository; this.superPomProvider = superPomProvider; + this.defaultSessionFactory = defaultSessionFactory; this.projectSelector = new ProjectSelector(); // if necessary switch to DI } @@ -229,8 +236,10 @@ private MavenExecutionResult doExecute( MavenExecutionRequest request ) DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession( request ); MavenSession session = new MavenSession( container, repoSession, request, result ); + session.setSession( defaultSessionFactory.getSession( session ) ); sessionScope.seed( MavenSession.class, session ); + sessionScope.seed( Session.class, session.getSession() ); legacySupport.setSession( session ); @@ -562,7 +571,7 @@ private void validatePrerequisitesForNonMavenPluginProjects( List { if ( !"maven-plugin".equals( mavenProject.getPackaging() ) ) { - Prerequisites prerequisites = mavenProject.getPrerequisites(); + Prerequisites prerequisites = mavenProject.getModel().getDelegate().getPrerequisites(); if ( prerequisites != null && prerequisites.getMaven() != null ) { logger.warn( "The project " + mavenProject.getId() + " uses prerequisites" @@ -596,9 +605,7 @@ private Set getAllProfiles( MavenSession session ) } final Stream projectProfiles = projectsIncludingParents.stream() - .map( MavenProject::getModel ) - .map( Model::getProfiles ) - .flatMap( Collection::stream ) + .flatMap( p -> p.getModel().getDelegate().getProfiles().stream() ) .map( Profile::getId ); final Stream settingsProfiles = session.getSettings().getProfiles().stream() .map( org.apache.maven.settings.Profile::getId ); diff --git a/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java b/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java index bb90aff28020..d0d2bf467103 100644 --- a/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java +++ b/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java @@ -70,6 +70,7 @@ public DefaultArtifactHandler( final String type ) ); } + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultArtifactHandler( final String type, final String extension, final String classifier, diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java index ed01875cf5cb..6d170896b8be 100644 --- a/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java @@ -20,6 +20,8 @@ */ import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Objects; import javax.inject.Named; @@ -31,10 +33,12 @@ import org.apache.maven.configuration.BeanConfigurationValuePreprocessor; import org.apache.maven.configuration.BeanConfigurator; import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.basic.AbstractBasicConverter; import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; -import org.codehaus.plexus.component.configurator.converters.lookup.DefaultConverterLookup; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; @@ -52,7 +56,12 @@ public class DefaultBeanConfigurator implements BeanConfigurator { - private final ConverterLookup converterLookup = new DefaultConverterLookup(); + private final ConverterLookup converterLookup; + + public DefaultBeanConfigurator() + { + converterLookup = new EnhancedConverterLookup(); + } public void configureBean( BeanConfigurationRequest request ) throws BeanConfigurationException @@ -94,11 +103,12 @@ else if ( configuration instanceof Xpp3Dom ) BeanExpressionEvaluator evaluator = new BeanExpressionEvaluator( request ); - ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter(); + ObjectWithFieldsConverter converter = new EnhancedConfigurationConverter(); try { - converter.processConfiguration( converterLookup, request.getBean(), classLoader, plexusConfig, evaluator ); + converter.processConfiguration( converterLookup, request.getBean(), classLoader, + plexusConfig, evaluator, null ); } catch ( ComponentConfigurationException e ) { @@ -154,4 +164,33 @@ public File alignToBaseDirectory( File file ) } + static class PathConverter extends AbstractBasicConverter + { + @Override + public boolean canConvert( Class type ) + { + return Path.class.equals( type ); + } + + @Override + protected Object fromString( String value ) throws ComponentConfigurationException + { + return Paths.get( value.replace( '/' == File.separatorChar ? '\\' : '/', File.separatorChar ) ); + } + + @Override + public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfiguration configuration, + final Class type, final Class enclosingType, final ClassLoader loader, + final ExpressionEvaluator evaluator, final ConfigurationListener listener ) + throws ComponentConfigurationException + { + final Object result = + super.fromConfiguration( lookup, configuration, type, enclosingType, loader, evaluator, listener ); + + return result instanceof Path + ? evaluator.alignToBaseDirectory( ( (Path) result ).toFile() ).toPath() : result; + } + + } + } diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java new file mode 100644 index 000000000000..defe38bcefb4 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java @@ -0,0 +1,67 @@ +package org.apache.maven.configuration.internal; + +/* + * 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. + */ + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.component.configurator.BasicComponentConfigurator; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.special.ClassRealmConverter; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.configuration.PlexusConfiguration; + +/** + * A component configurator which can leverage the {@link EnhancedConfigurationConverter} + * and {@link EnhancedConverterLookup}. + */ +@Singleton +@Named( "enhanced" ) +public class EnhancedComponentConfigurator + extends BasicComponentConfigurator +{ + + public EnhancedComponentConfigurator() + { + converterLookup = new EnhancedConverterLookup(); + } + + @Override + public void configureComponent( final Object component, final PlexusConfiguration configuration, + final ExpressionEvaluator evaluator, final ClassRealm realm, + final ConfigurationListener listener ) + throws ComponentConfigurationException + { + try + { + ClassRealmConverter.pushContextRealm( realm ); + + new EnhancedConfigurationConverter().processConfiguration( converterLookup, component, realm, // + configuration, evaluator, listener ); + } + finally + { + ClassRealmConverter.popContextRealm(); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java new file mode 100644 index 000000000000..8bab9a9c1245 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java @@ -0,0 +1,125 @@ +package org.apache.maven.configuration.internal; + +/* + * 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. + */ + +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; +import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.eclipse.sisu.plexus.CompositeBeanHelper; + +/** + * An enhanced {@link ObjectWithFieldsConverter} leveraging the {@link TypeAwareExpressionEvaluator} + * interface. + */ +class EnhancedConfigurationConverter + extends ObjectWithFieldsConverter +{ + protected Object fromExpression( final PlexusConfiguration configuration, final ExpressionEvaluator evaluator, + final Class type ) + throws ComponentConfigurationException + { + String value = configuration.getValue(); + try + { + Object result = null; + if ( null != value && value.length() > 0 ) + { + if ( evaluator instanceof TypeAwareExpressionEvaluator ) + { + result = ( (TypeAwareExpressionEvaluator) evaluator ).evaluate( value, type ); + } + else + { + result = evaluator.evaluate( value ); + } + } + if ( null == result && configuration.getChildCount() == 0 ) + { + value = configuration.getAttribute( "default-value" ); + if ( null != value && value.length() > 0 ) + { + if ( evaluator instanceof TypeAwareExpressionEvaluator ) + { + result = ( (TypeAwareExpressionEvaluator) evaluator ).evaluate( value, type ); + } + else + { + result = evaluator.evaluate( value ); + } + } + } + failIfNotTypeCompatible( result, type, configuration ); + return result; + } + catch ( final ExpressionEvaluationException e ) + { + final String reason = + String.format( "Cannot evaluate expression '%s' for configuration entry '%s'", value, + configuration.getName() ); + + throw new ComponentConfigurationException( configuration, reason, e ); + } + } + + + public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfiguration configuration, + final Class type, final Class enclosingType, final ClassLoader loader, + final ExpressionEvaluator evaluator, final ConfigurationListener listener ) + throws ComponentConfigurationException + { + final Object value = fromExpression( configuration, evaluator, type ); + if ( type.isInstance( value ) ) + { + return value; + } + try + { + final Class implType = getClassForImplementationHint( type, configuration, loader ); + if ( null == value && implType.isInterface() && configuration.getChildCount() == 0 ) + { + return null; // nothing to process + } + final Object bean = instantiateObject( implType ); + if ( null == value ) + { + processConfiguration( lookup, bean, loader, configuration, evaluator, listener ); + } + else + { + new CompositeBeanHelper( lookup, loader, evaluator, listener ) + .setDefault( bean, value, configuration ); + } + return bean; + } + catch ( final ComponentConfigurationException e ) + { + if ( null == e.getFailedConfiguration() ) + { + e.setFailedConfiguration( configuration ); + } + throw e; + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java new file mode 100644 index 000000000000..9399cec11788 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java @@ -0,0 +1,50 @@ +package org.apache.maven.configuration.internal; + +/* + * 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. + */ + +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.converters.ConfigurationConverter; +import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; +import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; +import org.codehaus.plexus.component.configurator.converters.lookup.DefaultConverterLookup; + +class EnhancedConverterLookup implements ConverterLookup +{ + private final ConverterLookup delegate = new DefaultConverterLookup(); + + EnhancedConverterLookup() + { + registerConverter( new DefaultBeanConfigurator.PathConverter() ); + } + + @Override + public void registerConverter( ConfigurationConverter converter ) + { + delegate.registerConverter( converter ); + } + + @Override + public ConfigurationConverter lookupConverterForType( Class type ) throws ComponentConfigurationException + { + ConfigurationConverter converter = delegate.lookupConverterForType( type ); + return converter.getClass().equals( ObjectWithFieldsConverter.class ) + ? new EnhancedConfigurationConverter() : converter; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java index 94e9eccd4ab3..6737c81aa3b9 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java +++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java @@ -283,7 +283,7 @@ public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) { - request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile ) ); + request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile.getDelegate() ) ); if ( settings.getActiveProfiles().contains( rawProfile.getId() ) ) { @@ -292,7 +292,8 @@ public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request { try { - request.addRemoteRepository( repositorySystem.buildArtifactRepository( remoteRepository ) ); + request.addRemoteRepository( + MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); } catch ( InvalidRepositoryException e ) { @@ -305,7 +306,8 @@ public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request { try { - request.addPluginArtifactRepository( repositorySystem.buildArtifactRepository( pluginRepo ) ); + request.addPluginArtifactRepository( + MavenRepositorySystem.buildArtifactRepository( pluginRepo ) ); } catch ( InvalidRepositoryException e ) { diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java index 4551ccffad54..3617438e81ad 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java @@ -27,14 +27,20 @@ import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; +import org.apache.maven.api.Session; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.RepositoryCache; import org.apache.maven.monitor.event.EventDispatcher; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; +import org.apache.maven.settings.SettingsUtils; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.eclipse.aether.RepositorySystemSession; @@ -297,6 +303,8 @@ public void setAllProjects( List allProjects ) private final Settings settings; + private Session session; + @Deprecated /** @deprecated This appears not to be used anywhere within Maven itself. */ public Map getProjectMap() @@ -311,7 +319,7 @@ public MavenSession( PlexusContainer container, RepositorySystemSession reposito this.container = container; this.request = request; this.result = result; - this.settings = new SettingsAdapter( request ); + this.settings = adaptSettings( request ); this.repositorySession = repositorySession; } @@ -357,10 +365,33 @@ public MavenSession( PlexusContainer container, MavenExecutionRequest request, M this.container = container; this.request = request; this.result = result; - this.settings = new SettingsAdapter( request ); + this.settings = adaptSettings( request ); setProjects( projects ); } + /** + * Adapt a {@link MavenExecutionRequest} to a {@link Settings} object for use in the Maven core. + * We want to make sure that what is ask for in the execution request overrides what is in the settings. + * The CLI feeds into an execution request so if a particular value is present in the execution request + * then we will take that over the value coming from the user settings. + */ + private static Settings adaptSettings( MavenExecutionRequest request ) + { + File localRepo = request.getLocalRepositoryPath(); + return new Settings( org.apache.maven.api.settings.Settings.newBuilder() + .localRepository( localRepo != null ? localRepo.getAbsolutePath() : null ) + .interactiveMode( request.isInteractiveMode() ) + .offline( request.isOffline() ) + .proxies( request.getProxies().stream().map( Proxy::getDelegate ).collect( Collectors.toList() ) ) + .servers( request.getServers().stream().map( Server::getDelegate ).collect( Collectors.toList() ) ) + .mirrors( request.getMirrors().stream().map( Mirror::getDelegate ).collect( Collectors.toList() ) ) + .profiles( request.getProfiles().stream() + .map( SettingsUtils::convertToSettingsProfile ).collect( Collectors.toList() ) ) + .activeProfiles( request.getActiveProfiles() ) + .pluginGroups( request.getPluginGroups() ) + .build() ); + } + @Deprecated public List getSortedProjects() { @@ -439,5 +470,14 @@ public Map lookupMap( String role ) return container.lookupMap( role ); } + public Session getSession() + { + return session; + } + + public void setSession( Session session ) + { + this.session = session; + } /*end[MAVEN4]*/ } diff --git a/maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java b/maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java deleted file mode 100644 index bf5d3730ec7d..000000000000 --- a/maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.apache.maven.execution; - -/* - * 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. - */ - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.RuntimeInfo; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.SettingsUtils; - -/** - * Adapt a {@link MavenExecutionRequest} to a {@link Settings} object for use in the Maven core. - * We want to make sure that what is ask for in the execution request overrides what is in the settings. - * The CLI feeds into an execution request so if a particular value is present in the execution request - * then we will take that over the value coming from the user settings. - * - * @author Jason van Zyl - */ -class SettingsAdapter - extends Settings -{ - - private MavenExecutionRequest request; - - private RuntimeInfo runtimeInfo; - - SettingsAdapter( MavenExecutionRequest request ) - { - this.request = request; - - /* - * NOTE: Plugins like maven-release-plugin query the path to the settings.xml to pass it into a forked Maven and - * the CLI will fail when called with a non-existing settings, so be sure to only point at actual files. Having - * a null file should be harmless as this case matches general Maven 2.x behavior... - */ - File userSettings = request.getUserSettingsFile(); - this.runtimeInfo = new RuntimeInfo( ( userSettings != null && userSettings.isFile() ) ? userSettings : null ); - } - - @Override - public String getLocalRepository() - { - if ( request.getLocalRepositoryPath() != null ) - { - return request.getLocalRepositoryPath().getAbsolutePath(); - } - - return null; - } - - @Override - public boolean isInteractiveMode() - { - return request.isInteractiveMode(); - } - - @Override - public boolean isOffline() - { - return request.isOffline(); - } - - @Override - public List getProxies() - { - return request.getProxies(); - } - - @Override - public List getServers() - { - return request.getServers(); - } - - @Override - public List getMirrors() - { - return request.getMirrors(); - } - - @Override - public List getProfiles() - { - List result = new ArrayList<>(); - for ( org.apache.maven.model.Profile profile : request.getProfiles() ) - { - result.add( SettingsUtils.convertToSettingsProfile( profile ) ); - } - return result; - } - - @Override - public List getActiveProfiles() - { - return request.getActiveProfiles(); - } - - @Override - public List getPluginGroups() - { - return request.getPluginGroups(); - } -} diff --git a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java index 9b2617fe5d87..0420b6054e40 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java +++ b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java @@ -19,14 +19,14 @@ * under the License. */ +import com.google.inject.AbstractModule; +import org.apache.maven.api.plugin.Log; import org.apache.maven.execution.scope.MojoExecutionScoped; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import com.google.inject.AbstractModule; - /** * MojoExecutionScopeModule */ @@ -51,9 +51,12 @@ protected void configure() { bindScope( MojoExecutionScoped.class, scope ); bind( MojoExecutionScope.class ).toInstance( scope ); - bind( MavenProject.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); bind( MojoExecution.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); + bind( Log.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); + bind( org.apache.maven.api.Project.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); + bind( org.apache.maven.api.MojoExecution.class ) + .toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index 4eacf7b399df..d8e187646b49 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -26,17 +26,22 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.xml.Dom; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.feature.Features; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.model.building.TransformerContext; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.apache.maven.rtinfo.RuntimeInformation; @@ -47,8 +52,7 @@ import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; import org.apache.maven.settings.crypto.SettingsDecrypter; import org.apache.maven.settings.crypto.SettingsDecryptionResult; -import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.DefaultRepositorySystemSession; @@ -114,6 +118,7 @@ public class DefaultRepositorySystemSessionFactory private final RuntimeInformation runtimeInformation; + @SuppressWarnings( "checkstyle:ParameterNumber" ) @Inject public DefaultRepositorySystemSessionFactory( ArtifactHandlerManager artifactHandlerManager, @@ -135,6 +140,7 @@ public DefaultRepositorySystemSessionFactory( this.runtimeInformation = runtimeInformation; } + @SuppressWarnings( "checkstyle:methodLength" ) public DefaultRepositorySystemSession newRepositorySession( MavenExecutionRequest request ) { DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); @@ -149,18 +155,9 @@ public DefaultRepositorySystemSession newRepositorySession( MavenExecutionReques session.setOffline( request.isOffline() ); session.setChecksumPolicy( request.getGlobalChecksumPolicy() ); - if ( request.isNoSnapshotUpdates() ) - { - session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER ); - } - else if ( request.isUpdateSnapshots() ) - { - session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS ); - } - else - { - session.setUpdatePolicy( null ); - } + session.setUpdatePolicy( request.isNoSnapshotUpdates() + ? RepositoryPolicy.UPDATE_POLICY_NEVER + : request.isUpdateSnapshots() ? RepositoryPolicy.UPDATE_POLICY_ALWAYS : null ); int errorPolicy = 0; errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND @@ -193,18 +190,12 @@ else if ( request.isUpdateSnapshots() ) session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) ); } - if ( request.getWorkspaceReader() != null ) - { - session.setWorkspaceReader( request.getWorkspaceReader() ); - } - else - { - session.setWorkspaceReader( workspaceRepository ); - } + session.setWorkspaceReader( + request.getWorkspaceReader() != null ? request.getWorkspaceReader() : workspaceRepository ); DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest(); - decrypt.setProxies( request.getProxies() ); - decrypt.setServers( request.getServers() ); + decrypt.setProxies( Proxy.proxyToApiV4( request.getProxies() ) ); + decrypt.setServers( Server.serverToApiV4( request.getServers() ) ); SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt ); if ( logger.isDebugEnabled() ) @@ -224,7 +215,7 @@ else if ( request.isUpdateSnapshots() ) session.setMirrorSelector( mirrorSelector ); DefaultProxySelector proxySelector = new DefaultProxySelector(); - for ( Proxy proxy : decrypted.getProxies() ) + for ( org.apache.maven.api.settings.Proxy proxy : decrypted.getProxies() ) { AuthenticationBuilder authBuilder = new AuthenticationBuilder(); authBuilder.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() ); @@ -235,7 +226,7 @@ else if ( request.isUpdateSnapshots() ) session.setProxySelector( proxySelector ); DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector(); - for ( Server server : decrypted.getServers() ) + for ( org.apache.maven.api.settings.Server server : decrypted.getServers() ) { AuthenticationBuilder authBuilder = new AuthenticationBuilder(); authBuilder.addUsername( server.getUsername() ).addPassword( server.getPassword() ); @@ -244,17 +235,12 @@ else if ( request.isUpdateSnapshots() ) if ( server.getConfiguration() != null ) { - Xpp3Dom dom = (Xpp3Dom) server.getConfiguration(); - for ( int i = dom.getChildCount() - 1; i >= 0; i-- ) - { - Xpp3Dom child = dom.getChild( i ); - if ( "wagonProvider".equals( child.getName() ) ) - { - dom.removeChild( i ); - } - } - - XmlPlexusConfiguration config = new XmlPlexusConfiguration( dom ); + Dom dom = server.getConfiguration(); + List children = dom.getChildren().stream() + .filter( c -> !"wagonProvider".equals( c.getName() ) ) + .collect( Collectors.toList() ); + dom = new Xpp3Dom( dom.getName(), null, null, children, null ); + PlexusConfiguration config = XmlPlexusConfiguration.toPlexusConfiguration( dom ); configProps.put( "aether.connector.wagon.config." + server.getId(), config ); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java new file mode 100644 index 000000000000..199d7222167e --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java @@ -0,0 +1,86 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.apache.maven.api.Node; +import org.apache.maven.api.NodeVisitor; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyNode; + +public abstract class AbstractNode implements Node +{ + + abstract org.eclipse.aether.graph.DependencyNode getDependencyNode(); + + @Override + public boolean accept( NodeVisitor visitor ) + { + if ( visitor.enter( this ) ) + { + for ( Node child : getChildren() ) + { + if ( !child.accept( visitor ) ) + { + break; + } + } + } + return visitor.leave( this ); + } + + @Override + public Node filter( Predicate filter ) + { + List children = getChildren().stream().filter( filter ) + .map( n -> n.filter( filter ) ) + .collect( Collectors.toList() ); + return new WrapperNode( this, Collections.unmodifiableList( children ) ); + } + + @Override + public String asString() + { + StringBuilder sb = new StringBuilder(); + + DependencyNode node = getDependencyNode(); + Artifact artifact = node.getArtifact(); + sb.append( artifact ); + + Dependency dependency = node.getDependency(); + if ( dependency != null ) + { + sb.append( ":" ).append( dependency.getScope() ); + } + + return sb.toString(); + } + + @Override + public String toString() + { + return getDependencyNode().toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java new file mode 100644 index 000000000000..de1bfdc6299d --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -0,0 +1,623 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.File; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Listener; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; +import org.apache.maven.api.Version; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.services.ArtifactCoordinateFactory; +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactDeployerException; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactInstallerException; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCollectorException; +import org.apache.maven.api.services.DependencyCoordinateFactory; +import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.VersionParser; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.project.MavenProject; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public abstract class AbstractSession implements Session +{ + + private final List listeners = new CopyOnWriteArrayList<>(); + private final Map allNodes + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allArtifacts + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allRepositories + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allProjects + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allDependencies + = Collections.synchronizedMap( new WeakHashMap<>() ); + + public RemoteRepository getRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository ) + { + return allRepositories.computeIfAbsent( repository, DefaultRemoteRepository::new ); + } + + public Node getNode( org.eclipse.aether.graph.DependencyNode node ) + { + return getNode( node, false ); + } + + public Node getNode( org.eclipse.aether.graph.DependencyNode node, boolean verbose ) + { + return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n, verbose ) ); + } + + @Nonnull + public Artifact getArtifact( @Nonnull org.eclipse.aether.artifact.Artifact artifact ) + { + return allArtifacts.computeIfAbsent( artifact, a -> new DefaultArtifact( this, a ) ); + } + + @Nonnull + public Dependency getDependency( @Nonnull org.eclipse.aether.graph.Dependency dependency ) + { + return allDependencies.computeIfAbsent( dependency, d -> new DefaultDependency( this, d ) ); + } + + public List getProjects( List projects ) + { + return projects == null ? null : projects.stream() + .map( this::getProject ) + .collect( Collectors.toList() ); + } + + public Project getProject( MavenProject project ) + { + return allProjects.computeIfAbsent( project.getId(), id -> new DefaultProject( this, project ) ); + } + + public List toRepositories( List repositories ) + { + return repositories == null ? null : repositories.stream() + .map( this::toRepository ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.repository.RemoteRepository toRepository( RemoteRepository repository ) + { + if ( repository instanceof DefaultRemoteRepository ) + { + return ( (DefaultRemoteRepository) repository ).getRepository(); + } + else + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + } + + public org.eclipse.aether.repository.LocalRepository toRepository( LocalRepository repository ) + { + if ( repository instanceof DefaultLocalRepository ) + { + return ( (DefaultLocalRepository) repository ).getRepository(); + } + else + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + } + + public List toArtifactRepositories( List repositories ) + { + return repositories == null ? null : repositories.stream() + .map( this::toArtifactRepository ) + .collect( Collectors.toList() ); + } + + public abstract ArtifactRepository toArtifactRepository( RemoteRepository repository ); + + public List toDependencies( Collection dependencies ) + { + return dependencies == null ? null : dependencies.stream() + .map( this::toDependency ) + .collect( Collectors.toList() ); + } + + public abstract org.eclipse.aether.graph.Dependency toDependency( DependencyCoordinate dependency ); + + public List toArtifacts( Collection artifacts ) + { + return artifacts == null ? null : artifacts.stream() + .map( this::toArtifact ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) + { + File file = getService( ArtifactManager.class ).getPath( artifact ).map( Path::toFile ).orElse( null ); + if ( artifact instanceof DefaultArtifact ) + { + org.eclipse.aether.artifact.Artifact a = ( (DefaultArtifact) artifact ).getArtifact(); + if ( Objects.equals( file, a.getFile() ) ) + { + return a; + } + } + return new org.eclipse.aether.artifact.DefaultArtifact( + artifact.getGroupId(), + artifact.getArtifactId(), + artifact.getClassifier(), + artifact.getExtension(), + artifact.getVersion().toString(), + null, + file + ); + } + + public org.eclipse.aether.artifact.Artifact toArtifact( ArtifactCoordinate coord ) + { + if ( coord instanceof DefaultArtifactCoordinate ) + { + return ( (DefaultArtifactCoordinate) coord ).getCoordinate(); + } + return new org.eclipse.aether.artifact.DefaultArtifact( + coord.getGroupId(), + coord.getArtifactId(), + coord.getClassifier(), + coord.getExtension(), + coord.getVersion().toString(), + null, + (File) null + ); + } + + public org.eclipse.aether.metadata.Metadata toMetadata( Metadata metadata ) + { + /* + if ( metadata instanceof ProjectArtifactMetadata ) + { + Artifact pomArtifact = new SubArtifact( mainArtifact, "", "pom" ); + pomArtifact = pomArtifact.setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ); + request.addArtifact( pomArtifact ); + } + else if ( // metadata instanceof SnapshotArtifactRepositoryMetadata || + metadata instanceof ArtifactRepositoryMetadata ) + { + // eaten, handled by repo system + } + else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.ArtifactMetadata ) + { + org.apache.maven.shared.transfer.metadata.ArtifactMetadata transferMetadata = + (org.apache.maven.shared.transfer.metadata.ArtifactMetadata) metadata; + + request.addMetadata( new Maven31MetadataBridge( metadata ).setFile( transferMetadata.getFile() ) ); + } + + */ + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public void registerListener( @Nonnull Listener listener ) + { + listeners.add( nonNull( listener ) ); + } + + @Override + public void unregisterListener( @Nonnull Listener listener ) + { + listeners.remove( nonNull( listener ) ); + } + + @Nonnull + @Override + public Collection getListeners() + { + return Collections.unmodifiableCollection( listeners ); + } + + // + // Shortcut implementations + // + + /** + * Shortcut for getService(RepositoryFactory.class).createLocal(...) + * + * @see RepositoryFactory#createLocal(Path) + */ + @Override + public LocalRepository createLocalRepository( Path path ) + { + return getService( RepositoryFactory.class ).createLocal( path ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * + * @see RepositoryFactory#createRemote(String, String) + */ + @Nonnull + @Override + public RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ) + { + return getService( RepositoryFactory.class ) + .createRemote( id, url ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * + * @see RepositoryFactory#createRemote(Repository) + */ + @Nonnull + @Override + public RemoteRepository createRemoteRepository( @Nonnull Repository repository ) + { + return getService( RepositoryFactory.class ) + .createRemote( repository ); + } + + /** + * Shortcut for getService(CoordinateFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String) + */ + @Override + public ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, + String version, String extension ) + { + return getService( ArtifactCoordinateFactory.class ) + .create( this, groupId, artifactId, version, extension ); + } + + /** + * Shortcut for getService(CoordinateFactory.class).create(...) + * + * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version, + String classifier, String extension, String type ) + { + return getService( ArtifactCoordinateFactory.class ) + .create( this, groupId, artifactId, version, classifier, extension, type ); + } + + /** + * Shortcut for getService(CoordinateFactory.class).create(...) + * + * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public ArtifactCoordinate createArtifactCoordinate( Artifact artifact ) + { + return getService( ArtifactCoordinateFactory.class ) + .create( this, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(), + artifact.getClassifier(), artifact.getExtension(), null ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String) + */ + @Override + public Artifact createArtifact( String groupId, String artifactId, String version, String extension ) + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, extension ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public Artifact createArtifact( String groupId, String artifactId, String version, String classifier, + String extension, String type ) + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, classifier, extension, type ); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Collection) + */ + @Override + public Artifact resolveArtifact( ArtifactCoordinate coordinate ) + { + return getService( ArtifactResolver.class ) + .resolve( this, Collections.singletonList( coordinate ) ) + .getArtifacts().keySet().iterator().next(); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Collection) + */ + @Override + public Collection resolveArtifacts( ArtifactCoordinate... coordinates ) + { + return resolveArtifacts( Arrays.asList( coordinates ) ); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Collection) + */ + @Override + public Collection resolveArtifacts( Collection coordinates ) + { + return getService( ArtifactResolver.class ) + .resolve( this, coordinates ) + .getArtifacts().keySet(); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Collection) + */ + @Override + public Artifact resolveArtifact( Artifact artifact ) + { + ArtifactCoordinate coordinate = getService( ArtifactCoordinateFactory.class ) + .create( this, artifact ); + return resolveArtifact( coordinate ); + } + + @Override + public Collection resolveArtifacts( Artifact... artifacts ) + { + ArtifactCoordinateFactory acf = getService( ArtifactCoordinateFactory.class ); + ArtifactCoordinate[] coords = Stream.of( artifacts ) + .map( a -> acf.create( this, a ) ) + .toArray( ArtifactCoordinate[]::new ); + return resolveArtifacts( coords ); + } + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * + * @throws ArtifactInstallerException if the artifacts installation failed + * @see ArtifactInstaller#install(Session, Collection) + */ + @Override + public void installArtifacts( Artifact... artifacts ) + { + installArtifacts( Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * + * @throws ArtifactInstallerException if the artifacts installation failed + * @see ArtifactInstaller#install(Session, Collection) + */ + @Override + public void installArtifacts( Collection artifacts ) + { + getService( ArtifactInstaller.class ) + .install( this, artifacts ); + } + + /** + * Shortcut for getService(ArtifactDeployer.class).deploy(...) + * + * @throws ArtifactDeployerException if the artifacts deployment failed + * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + */ + @Override + public void deployArtifact( RemoteRepository repository, Artifact... artifacts ) + { + getService( ArtifactDeployer.class ) + .deploy( this, repository, Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for getService(ArtifactManager.class).setPath(...) + * + * @see ArtifactManager#setPath(Artifact, Path) + */ + @Override + public void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ) + { + getService( ArtifactManager.class ) + .setPath( artifact, path ); + } + + /** + * Shortcut for getService(ArtifactManager.class).getPath(...) + * + * @see ArtifactManager#getPath(Artifact) + */ + @Nonnull + @Override + public Optional getArtifactPath( @Nonnull Artifact artifact ) + { + return getService( ArtifactManager.class ) + .getPath( artifact ); + } + + /** + * Shortcut for getService(VersionParser.class).isSnapshot(...) + * + * @see VersionParser#isSnapshot(String) + */ + @Override + public boolean isVersionSnapshot( @Nonnull String version ) + { + return getService( VersionParser.class ) + .isSnapshot( version ); + } + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * + * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate) + */ + @Nonnull + @Override + public DependencyCoordinate createDependencyCoordinate( @Nonnull ArtifactCoordinate coordinate ) + { + return getService( DependencyCoordinateFactory.class ) + .create( this, coordinate ); + } + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * + * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate) + */ + @Nonnull + public DependencyCoordinate createDependencyCoordinate( @Nonnull Dependency dependency ) + { + return getService( DependencyCoordinateFactory.class ) + .create( this, dependency ); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Artifact) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Artifact artifact ) + { + return getService( DependencyCollector.class ) + .collect( this, artifact ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Project) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Project project ) + { + return getService( DependencyCollector.class ) + .collect( this, project ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, DependencyCoordinate) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull DependencyCoordinate dependency ) + { + return getService( DependencyCollector.class ) + .collect( this, dependency ) + .getRoot(); + } + + @Override + public Path getPathForLocalArtifact( @Nonnull Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalArtifact( this, getLocalRepository(), artifact ); + } + + @Override + public Path getPathForLocalMetadata( Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalMetadata( this, getLocalRepository(), metadata ); + } + + @Override + public Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact ); + } + + @Override + public Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); + } + + @Override + public Version parseVersion( String version ) + { + return getService( VersionParser.class ) + .parseVersion( version ); + } + + @Override + public VersionRange parseVersionRange( String versionRange ) + { + return getService( VersionParser.class ) + .parseVersionRange( versionRange ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java new file mode 100644 index 000000000000..54b5ff372501 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -0,0 +1,128 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Version; +import org.apache.maven.api.annotations.Nonnull; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +/** + * A wrapper class around a maven resolver artifact. + */ +public class DefaultArtifact implements Artifact +{ + private final @Nonnull AbstractSession session; + private final @Nonnull org.eclipse.aether.artifact.Artifact artifact; + private final String id; + + public DefaultArtifact( @Nonnull AbstractSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact ) + { + this.session = nonNull( session, "session can not be null" ); + this.artifact = nonNull( artifact, "artifact can not be null" ); + this.id = getGroupId() + + ':' + getArtifactId() + + ':' + getExtension() + + ( getClassifier().length() > 0 ? ":" + getClassifier() : "" ) + + ':' + getVersion(); + } + + public org.eclipse.aether.artifact.Artifact getArtifact() + { + return artifact; + } + + @Override + public String key() + { + return id; + } + + @Nonnull + @Override + public String getGroupId() + { + return artifact.getGroupId(); + } + + @Nonnull + @Override + public String getArtifactId() + { + return artifact.getArtifactId(); + } + + @Nonnull + @Override + public Version getVersion() + { + return session.parseVersion( artifact.getVersion() ); + } + + @Nonnull + @Override + public String getExtension() + { + return artifact.getExtension(); + } + + @Nonnull + @Override + public String getClassifier() + { + return artifact.getClassifier(); + } + + @Override + public boolean isSnapshot() + { + return DefaultVersionParser.checkSnapshot( artifact.getVersion() ); + } + + @Nonnull + @Override + public ArtifactCoordinate toCoordinate() + { + return session.createArtifactCoordinate( this ); + } + + @Override + public boolean equals( Object o ) + { + return o instanceof DefaultArtifact + && Objects.equals( id, ( (DefaultArtifact) o ).id ); + } + + @Override + public int hashCode() + { + return id.hashCode(); + } + + @Override + public String toString() + { + return artifact.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinate.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinate.java new file mode 100644 index 000000000000..3386ff56e588 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinate.java @@ -0,0 +1,113 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +/** + * A wrapper class around a maven resolver artifact. + */ +public class DefaultArtifactCoordinate implements ArtifactCoordinate +{ + private final @Nonnull AbstractSession session; + private final @Nonnull org.eclipse.aether.artifact.Artifact coordinate; + + public DefaultArtifactCoordinate( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.artifact.Artifact coordinate ) + { + this.session = nonNull( session, "session can not be null" ); + this.coordinate = nonNull( coordinate, "coordinate can not be null" ); + } + + public org.eclipse.aether.artifact.Artifact getCoordinate() + { + return coordinate; + } + + @Nonnull + @Override + public String getGroupId() + { + return coordinate.getGroupId(); + } + + @Nonnull + @Override + public String getArtifactId() + { + return coordinate.getArtifactId(); + } + + @Nonnull + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( coordinate.getVersion() ); + } + + @Override + public String getExtension() + { + return coordinate.getExtension(); + } + + @Nonnull + @Override + public String getClassifier() + { + return coordinate.getClassifier(); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + DefaultArtifactCoordinate that = (DefaultArtifactCoordinate) o; + return Objects.equals( this.getGroupId(), that.getGroupId() ) + && Objects.equals( this.getArtifactId(), that.getArtifactId() ) + && Objects.equals( this.getVersion(), that.getVersion() ) + && Objects.equals( this.getClassifier(), that.getClassifier() ); + } + + @Override + public int hashCode() + { + return Objects.hash( getGroupId(), getArtifactId(), getVersion(), getClassifier() ); + } + + @Override + public String toString() + { + return coordinate.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinateFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinateFactory.java new file mode 100644 index 000000000000..b6edcd57264a --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinateFactory.java @@ -0,0 +1,62 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Named; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.ArtifactCoordinateFactory; +import org.apache.maven.api.services.ArtifactCoordinateFactoryRequest; +import org.apache.maven.shared.utils.StringUtils; +import org.eclipse.aether.artifact.ArtifactType; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +@Named +public class DefaultArtifactCoordinateFactory implements ArtifactCoordinateFactory +{ + @Override + public ArtifactCoordinate create( @Nonnull ArtifactCoordinateFactoryRequest request ) + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + ArtifactType type = null; + if ( request.getType() != null ) + { + type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); + } + String classifier = StringUtils.isNotEmpty( request.getClassifier() ) + ? request.getClassifier() : type != null ? type.getClassifier() : ""; + String extension = StringUtils.isNotEmpty( request.getExtension() ) + ? request.getExtension() : type != null ? type.getExtension() : ""; + return new DefaultArtifactCoordinate( + session, + new org.eclipse.aether.artifact.DefaultArtifact( + request.getGroupId(), + request.getArtifactId(), + classifier, + extension, + request.getVersion(), + type ) ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java new file mode 100644 index 000000000000..f6be945bf2b2 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java @@ -0,0 +1,87 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; +import javax.inject.Named; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactDeployerException; +import org.apache.maven.api.services.ArtifactDeployerRequest; +import org.apache.maven.api.services.ArtifactManager; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.deployment.DeployRequest; +import org.eclipse.aether.deployment.DeployResult; +import org.eclipse.aether.deployment.DeploymentException; +import org.eclipse.aether.metadata.Metadata; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +/** + * Implementation of {@link ArtifactDeployer} service. + */ +@Named +public class DefaultArtifactDeployer implements ArtifactDeployer +{ + private final @Nonnull RepositorySystem repositorySystem; + + @Inject + DefaultArtifactDeployer( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = nonNull( repositorySystem, "repositorySystem can not be null" ); + } + + @Override + public void deploy( @Nonnull ArtifactDeployerRequest request ) + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + Collection artifacts = nonNull( request.getArtifacts(), "request.artifacts can not be null" ); + RemoteRepository repository = nonNull( request.getRepository(), "request.repository can not be null" ); + try + { + ArtifactManager artifactManager = session.getService( ArtifactManager.class ); + List metadatas = artifacts.stream() + .map( artifactManager::getAttachedMetadatas ) + .flatMap( Collection::stream ) + .map( session::toMetadata ) + .collect( Collectors.toList() ); + DeployRequest deployRequest = new DeployRequest() + .setRepository( session.toRepository( repository ) ) + .setArtifacts( session.toArtifacts( artifacts ) ) + .setMetadata( metadatas ); + + DeployResult result = repositorySystem.deploy( session.getSession(), deployRequest ); + } + catch ( DeploymentException e ) + { + throw new ArtifactDeployerException( "Unable to deploy artifacts", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java new file mode 100644 index 000000000000..c5dd9a1c2104 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java @@ -0,0 +1,63 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Named; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactFactoryRequest; +import org.apache.maven.shared.utils.StringUtils; +import org.eclipse.aether.artifact.ArtifactType; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +@Named +public class DefaultArtifactFactory implements ArtifactFactory +{ + @Override + public Artifact create( @Nonnull ArtifactFactoryRequest request ) + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + ArtifactType type = null; + if ( request.getType() != null ) + { + type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); + } + String classifier = StringUtils.isNotEmpty( request.getClassifier() ) + ? request.getClassifier() + : type != null ? type.getClassifier() : null; + String extension = StringUtils.isNotEmpty( request.getExtension() ) + ? request.getExtension() : type != null ? type.getExtension() : null; + return new DefaultArtifact( + session, + new org.eclipse.aether.artifact.DefaultArtifact( + request.getGroupId(), + request.getArtifactId(), + classifier, + extension, + request.getVersion(), + type ) ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java new file mode 100644 index 000000000000..dba2fa80a469 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java @@ -0,0 +1,76 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactInstallerException; +import org.apache.maven.api.services.ArtifactInstallerRequest; +import org.apache.maven.api.services.ArtifactManager; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.installation.InstallRequest; +import org.eclipse.aether.installation.InstallResult; +import org.eclipse.aether.installation.InstallationException; +import org.eclipse.aether.metadata.Metadata; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultArtifactInstaller implements ArtifactInstaller +{ + + private final RepositorySystem repositorySystem; + + DefaultArtifactInstaller( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = nonNull( repositorySystem ); + } + + @Override + public void install( ArtifactInstallerRequest request ) throws ArtifactInstallerException, IllegalArgumentException + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + try + { + ArtifactManager artifactManager = session.getService( ArtifactManager.class ); + List metadatas = request.getArtifacts().stream() + .map( artifactManager::getAttachedMetadatas ) + .flatMap( Collection::stream ) + .map( session::toMetadata ) + .collect( Collectors.toList() ); + InstallRequest installRequest = new InstallRequest() + .setArtifacts( session.toArtifacts( request.getArtifacts() ) ) + .setMetadata( metadatas ); + + InstallResult result = repositorySystem.install( session.getSession(), installRequest ); + } + catch ( InstallationException e ) + { + throw new ArtifactInstallerException( e.getMessage(), e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java new file mode 100644 index 000000000000..69b9f991ed1d --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -0,0 +1,136 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.project.MavenProject; + +public class DefaultArtifactManager implements ArtifactManager +{ + + @Nonnull + private final DefaultSession session; + private final Map paths = new ConcurrentHashMap<>(); + private final Map> metadatas = new ConcurrentHashMap<>(); + + public DefaultArtifactManager( @Nonnull DefaultSession session ) + { + this.session = session; + } + + @Nonnull + @Override + public Optional getPath( @Nonnull Artifact artifact ) + { + if ( session.getMavenSession().getAllProjects() != null ) + { + String id = id( artifact ); + for ( MavenProject project : session.getMavenSession().getAllProjects() ) + { + if ( id.equals( id( project.getArtifact() ) ) && project.getArtifact().getFile() != null ) + { + return Optional.of( project.getArtifact().getFile().toPath() ); + } + } + } + Path path = paths.get( artifact ); + if ( path == null && artifact instanceof DefaultArtifact ) + { + File file = ( (DefaultArtifact) artifact ).getArtifact().getFile(); + if ( file != null ) + { + path = file.toPath(); + } + } + return Optional.ofNullable( path ); + } + + @Override + public void setPath( @Nonnull Artifact artifact, Path path ) + { + if ( session.getMavenSession().getAllProjects() != null ) + { + String id = id( artifact ); + for ( MavenProject project : session.getMavenSession().getAllProjects() ) + { + if ( id.equals( id( project.getArtifact() ) ) ) + { + project.getArtifact().setFile( path != null ? path.toFile() : null ); + break; + } + } + } + if ( path == null ) + { + paths.remove( artifact ); + } + else + { + paths.put( artifact, path ); + } + } + + @Nonnull + @Override + public Collection getAttachedMetadatas( @Nonnull Artifact artifact ) + { + Collection m = metadatas.get( artifact ); + return m != null ? Collections.unmodifiableCollection( m ) : Collections.emptyList(); + } + + @Override + public void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metadata ) + { + metadatas.computeIfAbsent( artifact, a -> new CopyOnWriteArrayList<>() ).add( metadata ); + } + + private String id( org.apache.maven.artifact.Artifact artifact ) + { + return artifact.getGroupId() + + ":" + artifact.getArtifactId() + + ":" + artifact.getType() + + ( artifact.getClassifier() == null || artifact.getClassifier().isEmpty() + ? "" : ":" + artifact.getClassifier() ) + + ":" + artifact.getVersion(); + } + + private String id( Artifact artifact ) + { + return artifact.getGroupId() + + ":" + artifact.getArtifactId() + + ":" + artifact.getExtension() + + ( artifact.getClassifier().isEmpty() ? "" : ":" + artifact.getClassifier() ) + + ":" + artifact.getVersion(); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java new file mode 100644 index 000000000000..dadb37acd786 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java @@ -0,0 +1,93 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.ArtifactResolverRequest; +import org.apache.maven.api.services.ArtifactResolverResult; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultArtifactResolver implements ArtifactResolver +{ + private final RepositorySystem repositorySystem; + + @Inject + DefaultArtifactResolver( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = nonNull( repositorySystem, "repositorySystem can not be null" ); + } + + @Override + public ArtifactResolverResult resolve( ArtifactResolverRequest request ) + throws ArtifactResolverException, IllegalArgumentException + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + try + { + List repositories = session.toRepositories( session.getRemoteRepositories() ); + List requests = request.getCoordinates().stream() + .map( coord -> new ArtifactRequest( session.toArtifact( coord ), repositories, null ) ) + .collect( Collectors.toList() ); + List results = repositorySystem.resolveArtifacts( session.getSession(), requests ); + Map paths = new HashMap<>(); + for ( ArtifactResult result : results ) + { + Artifact artifact = session.getArtifact( result.getArtifact() ); + Path path = result.getArtifact().getFile().toPath(); + session.getService( ArtifactManager.class ).setPath( artifact, path ); + paths.put( artifact, path ); + } + return new ArtifactResolverResult() + { + @Override + public Map getArtifacts() + { + return paths; + } + }; + } + catch ( ArtifactResolutionException e ) + { + throw new ArtifactResolverException( "Unable to resolve artifact", e ); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java new file mode 100644 index 000000000000..78b6eaddd8e1 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -0,0 +1,149 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; + +import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Scope; +import org.apache.maven.api.Type; +import org.apache.maven.api.Version; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.artifact.ArtifactProperties; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultDependency implements Dependency +{ + private final AbstractSession session; + private final org.eclipse.aether.graph.Dependency dependency; + private final String key; + + public DefaultDependency( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.graph.Dependency dependency ) + { + this.session = nonNull( session, "session" ); + this.dependency = nonNull( dependency, "dependency" ); + this.key = getGroupId() + + ':' + getArtifactId() + + ':' + getExtension() + + ( getClassifier().length() > 0 ? ":" + getClassifier() : "" ) + + ':' + getVersion(); + } + + @Override + public String key() + { + return key; + } + + @Nonnull + public org.eclipse.aether.graph.Dependency getDependency() + { + return dependency; + } + + @Override + public String getGroupId() + { + return dependency.getArtifact().getGroupId(); + } + + @Override + public String getArtifactId() + { + return dependency.getArtifact().getArtifactId(); + } + + @Override + public String getClassifier() + { + return dependency.getArtifact().getClassifier(); + } + + @Override + public Version getVersion() + { + return session.parseVersion( dependency.getArtifact().getVersion() ); + } + + @Override + public String getExtension() + { + return dependency.getArtifact().getExtension(); + } + + @Override + public Type getType() + { + String type = dependency.getArtifact().getProperty( ArtifactProperties.TYPE, + dependency.getArtifact().getExtension() ); + return session.getService( TypeRegistry.class ).getType( type ); + } + + @Override + public boolean isSnapshot() + { + return DefaultVersionParser.checkSnapshot( dependency.getArtifact().getVersion() ); + } + + @Nonnull + @Override + public Scope getScope() + { + return Scope.get( dependency.getScope() ); + } + + @Nullable + @Override + public boolean isOptional() + { + return dependency.isOptional(); + } + + @Nonnull + @Override + public DependencyCoordinate toCoordinate() + { + return session.createDependencyCoordinate( this ); + } + + @Override + public boolean equals( Object o ) + { + return o instanceof DefaultDependency + && Objects.equals( key, ( (DefaultDependency) o ).key ); + } + + @Override + public int hashCode() + { + return key.hashCode(); + } + + @Override + public String toString() + { + return dependency.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java new file mode 100644 index 000000000000..83ea3732a60d --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java @@ -0,0 +1,110 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; +import javax.inject.Named; + +import java.util.List; + +import org.apache.maven.api.Node; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCollectorException; +import org.apache.maven.api.services.DependencyCollectorRequest; +import org.apache.maven.api.services.DependencyCollectorResult; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.transformer.ConflictResolver; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +@Named +public class DefaultDependencyCollector implements DependencyCollector +{ + + private final RepositorySystem repositorySystem; + + @Inject + DefaultDependencyCollector( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = repositorySystem; + } + + @Nonnull + @Override + public DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ) + throws DependencyCollectorException, IllegalArgumentException + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + + Artifact rootArtifact = request.getRootArtifact().map( session::toArtifact ).orElse( null ); + Dependency root = request.getRoot().map( session::toDependency ).orElse( null ); + CollectRequest collectRequest = new CollectRequest() + .setRootArtifact( rootArtifact ) + .setRoot( root ) + .setDependencies( session.toDependencies( request.getDependencies() ) ) + .setManagedDependencies( session.toDependencies( request.getManagedDependencies() ) ) + .setRepositories( session.toRepositories( session.getRemoteRepositories() ) ); + + RepositorySystemSession systemSession = session.getSession(); + if ( request.getVerbose() ) + { + systemSession = new DefaultRepositorySystemSession( systemSession ) + .setConfigProperty( ConflictResolver.CONFIG_PROP_VERBOSE, true ) + .setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, true ); + } + + try + { + final CollectResult + result = repositorySystem.collectDependencies( systemSession, collectRequest ); + return new DependencyCollectorResult() + { + @Override + public List getExceptions() + { + return result.getExceptions(); + } + + @Override + public Node getRoot() + { + return session.getNode( result.getRoot(), request.getVerbose() ); + } + }; + } + catch ( DependencyCollectionException e ) + { + throw new DependencyCollectorException( "Unable to collect dependencies", e ); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java new file mode 100644 index 000000000000..f6b7862f0ae1 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java @@ -0,0 +1,132 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Collection; + +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Scope; +import org.apache.maven.api.Type; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.artifact.ArtifactProperties; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultDependencyCoordinate implements DependencyCoordinate +{ + private final AbstractSession session; + private final org.eclipse.aether.graph.Dependency dependency; + + public DefaultDependencyCoordinate( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.graph.Dependency dependency ) + { + this.session = nonNull( session, "session" ); + this.dependency = nonNull( dependency, "dependency" ); + } + + @Nonnull + public org.eclipse.aether.graph.Dependency getDependency() + { + return dependency; + } + + @Override + public String getGroupId() + { + return dependency.getArtifact().getGroupId(); + } + + @Override + public String getArtifactId() + { + return dependency.getArtifact().getArtifactId(); + } + + @Override + public String getClassifier() + { + return dependency.getArtifact().getClassifier(); + } + + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( dependency.getArtifact().getVersion() ); + } + + @Override + public String getExtension() + { + return dependency.getArtifact().getExtension(); + } + + @Override + public Type getType() + { + String type = dependency.getArtifact().getProperty( ArtifactProperties.TYPE, + dependency.getArtifact().getExtension() ); + return session.getService( TypeRegistry.class ).getType( type ); + } + + @Nonnull + @Override + public Scope getScope() + { + return Scope.get( dependency.getScope() ); + } + + @Nullable + @Override + public Boolean getOptional() + { + return dependency.getOptional(); + } + + @Nonnull + @Override + public Collection getExclusions() + { + return new MappedCollection<>( dependency.getExclusions(), this::toExclusion ); + } + + private Exclusion toExclusion( org.eclipse.aether.graph.Exclusion exclusion ) + { + return new Exclusion() + { + @Nullable + @Override + public String getGroupId() + { + return exclusion.getGroupId(); + } + + @Nullable + @Override + public String getArtifactId() + { + return exclusion.getArtifactId(); + } + }; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinateFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinateFactory.java new file mode 100644 index 000000000000..ae765e934301 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinateFactory.java @@ -0,0 +1,75 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Named; + +import java.util.stream.Collectors; + +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.DependencyCoordinateFactory; +import org.apache.maven.api.services.DependencyCoordinateFactoryRequest; +import org.eclipse.aether.artifact.ArtifactType; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +@Named +public class DefaultDependencyCoordinateFactory implements DependencyCoordinateFactory +{ + + @Nonnull + @Override + public DependencyCoordinate create( @Nonnull DependencyCoordinateFactoryRequest request ) + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + + ArtifactType type = null; + if ( request.getType() != null ) + { + type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); + } + return new DefaultDependencyCoordinate( + session, + new org.eclipse.aether.graph.Dependency( + new org.eclipse.aether.artifact.DefaultArtifact( + request.getGroupId(), + request.getArtifactId(), + request.getClassifier(), + request.getExtension(), + request.getVersion(), + type + ), + request.getScope(), + request.isOptional(), + request.getExclusions().stream().map( this::toExclusion ).collect( Collectors.toList() ) ) ); + } + + private org.eclipse.aether.graph.Exclusion toExclusion( Exclusion exclusion ) + { + return new org.eclipse.aether.graph.Exclusion( + exclusion.getGroupId(), exclusion.getArtifactId(), "*", "*" ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java new file mode 100644 index 000000000000..12f047fec67f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java @@ -0,0 +1,71 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Optional; + +import org.apache.maven.api.Event; +import org.apache.maven.api.EventType; +import org.apache.maven.api.MojoExecution; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.execution.ExecutionEvent; + +public class DefaultEvent implements Event +{ + private final AbstractSession session; + private final ExecutionEvent delegate; + + public DefaultEvent( AbstractSession session, ExecutionEvent delegate ) + { + this.session = session; + this.delegate = delegate; + } + + @Override + public EventType getType() + { + return EventType.valueOf( delegate.getType().name() ); + } + + @Override + public Session getSession() + { + return session; + } + + @Override + public Optional getProject() + { + return Optional.ofNullable( delegate.getProject() ).map( session::getProject ); + } + + @Override + public Optional getMojoExecution() + { + return Optional.ofNullable( delegate.getMojoExecution() ).map( DefaultMojoExecution::new ); + } + + @Override + public Optional getException() + { + return Optional.empty(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java new file mode 100644 index 000000000000..618333e1c824 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java @@ -0,0 +1,69 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; + +import java.nio.file.Path; + +import org.apache.maven.api.LocalRepository; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultLocalRepository implements LocalRepository +{ + + private final @Nonnull org.eclipse.aether.repository.LocalRepository repository; + + @Inject + public DefaultLocalRepository( @Nonnull org.eclipse.aether.repository.LocalRepository repository ) + { + this.repository = nonNull( repository, "repository can not be null" ); + } + + @Nonnull + public org.eclipse.aether.repository.LocalRepository getRepository() + { + return repository; + } + + @Nonnull + @Override + public String getId() + { + return repository.getId(); + } + + @Nonnull + @Override + public String getType() + { + return repository.getContentType(); + } + + @Nonnull + @Override + public Path getPath() + { + return repository.getBasedir().toPath(); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java new file mode 100644 index 000000000000..450791df609f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java @@ -0,0 +1,81 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; +import org.apache.maven.api.services.LocalRepositoryManager; + +public class DefaultLocalRepositoryManager implements LocalRepositoryManager +{ + + @Override + public Path getPathForLocalArtifact( Session session, LocalRepository local, Artifact artifact ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForLocalArtifact( s.toArtifact( artifact ) ); + return local.getPath().resolve( path ); + } + + @Override + public Path getPathForLocalMetadata( Session session, LocalRepository local, Metadata metadata ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForLocalMetadata( s.toMetadata( metadata ) ); + return local.getPath().resolve( path ); + } + + @Override + public Path getPathForRemoteArtifact( Session session, LocalRepository local, + RemoteRepository remote, Artifact artifact ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForRemoteArtifact( + s.toArtifact( artifact ), s.toRepository( remote ), null ); + return local.getPath().resolve( path ); + } + + @Override + public Path getPathForRemoteMetadata( Session session, LocalRepository local, + RemoteRepository remote, Metadata metadata ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForRemoteMetadata( + s.toMetadata( metadata ), s.toRepository( remote ), null ); + return local.getPath().resolve( path ); + } + + private org.eclipse.aether.repository.LocalRepositoryManager getManager( + DefaultSession session, LocalRepository local ) + { + org.eclipse.aether.repository.LocalRepository repository = session.toRepository( local ); + if ( "enhanced".equals( repository.getContentType() ) ) + { + repository = new org.eclipse.aether.repository.LocalRepository( repository.getBasedir(), "" ); + } + return session.getRepositorySystem().newLocalRepositoryManager( session.getSession(), repository ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java new file mode 100644 index 000000000000..0f044609199a --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java @@ -0,0 +1,210 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.function.Supplier; + +import org.apache.maven.api.plugin.Log; +import org.slf4j.Logger; + +import static java.util.Objects.requireNonNull; + +public class DefaultLog implements Log +{ + private final Logger logger; + + public DefaultLog( Logger logger ) + { + this.logger = requireNonNull( logger ); + } + + public void debug( CharSequence content ) + { + logger.debug( toString( content ) ); + } + + @Override + public void debug( CharSequence content, Throwable error ) + { + logger.debug( toString( content ), error ); + } + + @Override + public void debug( Throwable error ) + { + logger.debug( "", error ); + } + + @Override + public void debug( Supplier content ) + { + if ( isDebugEnabled() ) + { + logger.debug( content.get() ); + } + } + + @Override + public void debug( Supplier content, Throwable error ) + { + if ( isDebugEnabled() ) + { + logger.debug( content.get(), error ); + } + } + + @Override + public void info( CharSequence content ) + { + logger.info( toString( content ) ); + } + + @Override + public void info( CharSequence content, Throwable error ) + { + logger.info( toString( content ), error ); + } + + @Override + public void info( Throwable error ) + { + logger.info( "", error ); + } + + @Override + public void info( Supplier content ) + { + if ( isInfoEnabled() ) + { + logger.info( content.get() ); + } + } + + @Override + public void info( Supplier content, Throwable error ) + { + if ( isInfoEnabled() ) + { + logger.info( content.get(), error ); + } + } + + @Override + public void warn( CharSequence content ) + { + logger.warn( toString( content ) ); + } + + @Override + public void warn( CharSequence content, Throwable error ) + { + logger.warn( toString( content ), error ); + } + + @Override + public void warn( Throwable error ) + { + logger.warn( "", error ); + } + + @Override + public void warn( Supplier content ) + { + if ( isWarnEnabled() ) + { + logger.warn( content.get() ); + } + } + + @Override + public void warn( Supplier content, Throwable error ) + { + if ( isWarnEnabled() ) + { + logger.info( content.get(), error ); + } + } + + @Override + public void error( CharSequence content ) + { + logger.error( toString( content ) ); + } + + @Override + public void error( CharSequence content, Throwable error ) + { + logger.error( toString( content ), error ); + } + + @Override + public void error( Throwable error ) + { + logger.error( "", error ); + } + + @Override + public void error( Supplier content ) + { + if ( isErrorEnabled() ) + { + logger.error( content.get() ); + } + } + + @Override + public void error( Supplier content, Throwable error ) + { + if ( isErrorEnabled() ) + { + logger.error( content.get(), error ); + } + } + + @Override + public boolean isDebugEnabled() + { + return logger.isDebugEnabled(); + } + + @Override + public boolean isInfoEnabled() + { + return logger.isInfoEnabled(); + } + + @Override + public boolean isWarnEnabled() + { + return logger.isWarnEnabled(); + } + + @Override + public boolean isErrorEnabled() + { + return logger.isErrorEnabled(); + } + + private String toString( CharSequence content ) + { + return content != null ? content.toString() : ""; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java new file mode 100644 index 000000000000..9df503cd7d8f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java @@ -0,0 +1,91 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.services.Lookup; +import org.apache.maven.api.services.LookupException; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; + +public class DefaultLookup implements Lookup +{ + + private final PlexusContainer container; + + public DefaultLookup( PlexusContainer container ) + { + this.container = container; + } + + @Override + public T lookup( Class type ) + { + try + { + return container.lookup( type ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } + + @Override + public T lookup( Class type, String name ) + { + try + { + return container.lookup( type, name ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } + + @Override + public List lookupList( Class type ) + { + try + { + return container.lookupList( type ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } + + @Override + public Map lookupMap( Class type ) + { + try + { + return container.lookupMap( type ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java new file mode 100644 index 000000000000..088258f0116f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java @@ -0,0 +1,146 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.MessageBuilder; + +@Experimental +public class DefaultMessageBuilder implements MessageBuilder +{ + private final @Nonnull org.apache.maven.shared.utils.logging.MessageBuilder delegate; + + public DefaultMessageBuilder( @Nonnull org.apache.maven.shared.utils.logging.MessageBuilder delegate ) + { + this.delegate = delegate; + } + + @Override + @Nonnull + public MessageBuilder success( Object o ) + { + delegate.success( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder warning( Object o ) + { + delegate.warning( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder failure( Object o ) + { + delegate.failure( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder strong( Object o ) + { + delegate.strong( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder mojo( Object o ) + { + delegate.mojo( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder project( Object o ) + { + delegate.project( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( char[] chars, int i, int i1 ) + { + delegate.a( chars, i, i1 ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( char[] chars ) + { + delegate.a( chars ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( CharSequence charSequence, int i, int i1 ) + { + delegate.a( charSequence, i, i1 ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( CharSequence charSequence ) + { + delegate.a( charSequence ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( Object o ) + { + delegate.a( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder newline() + { + delegate.newline(); + return this; + } + + @Override + @Nonnull + public MessageBuilder format( String s, Object... objects ) + { + delegate.format( s, objects ); + return this; + } + + @Override + @Nonnull + public String build() + { + return delegate.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java new file mode 100644 index 000000000000..078ca08b15c6 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java @@ -0,0 +1,60 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; +import org.apache.maven.shared.utils.logging.MessageUtils; + +@Experimental +public class DefaultMessageBuilderFactory implements MessageBuilderFactory +{ + + @Override + public boolean isColorEnabled() + { + return MessageUtils.isColorEnabled(); + } + + @Override + public int getTerminalWidth() + { + return MessageUtils.getTerminalWidth(); + } + + @Override + @Nonnull + public MessageBuilder builder() + { + return new DefaultMessageBuilder( MessageUtils.buffer() ); + } + + @Override + @Nonnull + public MessageBuilder builder( @Nonnull StringBuilder stringBuilder ) + { + return new DefaultMessageBuilder( MessageUtils.buffer( Objects.requireNonNull( stringBuilder ) ) ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java new file mode 100644 index 000000000000..c8079351e1e8 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java @@ -0,0 +1,123 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.xml.ModelXmlFactory; +import org.apache.maven.api.services.xml.XmlReaderException; +import org.apache.maven.api.services.xml.XmlReaderRequest; +import org.apache.maven.api.services.xml.XmlWriterException; +import org.apache.maven.api.services.xml.XmlWriterRequest; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenXpp3ReaderEx; +import org.apache.maven.model.v4.MavenXpp3WriterEx; +import org.codehaus.plexus.util.ReaderFactory; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultModelXmlFactory + implements ModelXmlFactory +{ + @Override + public Model read( @Nonnull XmlReaderRequest request ) throws XmlReaderException + { + nonNull( request, "request can not be null" ); + Path path = request.getPath(); + URL url = request.getURL(); + Reader reader = request.getReader(); + InputStream inputStream = request.getInputStream(); + if ( path == null && url == null && reader == null && inputStream == null ) + { + throw new IllegalArgumentException( "path, url, reader or inputStream must be non null" ); + } + try + { + InputSource source = null; + if ( request.getModelId() != null || request.getLocation() != null ) + { + source = new InputSource( request.getModelId(), request.getLocation() ); + } + MavenXpp3ReaderEx xml = new MavenXpp3ReaderEx(); + xml.setAddDefaultEntities( request.isAddDefaultEntities() ); + if ( path != null ) + { + reader = ReaderFactory.newXmlReader( path.toFile() ); + } + else if ( url != null ) + { + reader = ReaderFactory.newXmlReader( url ); + } + else if ( inputStream != null ) + { + reader = ReaderFactory.newXmlReader( inputStream ); + } + return xml.read( reader, request.isStrict(), source ); + } + catch ( Exception e ) + { + throw new XmlReaderException( "Unable to read model", e ); + } + } + + @Override + public void write( XmlWriterRequest request ) throws XmlWriterException + { + nonNull( request, "request can not be null" ); + Model content = nonNull( request.getContent(), "content can not be null" ); + Path path = request.getPath(); + OutputStream outputStream = request.getOutputStream(); + Writer writer = request.getWriter(); + if ( writer == null && outputStream == null && path == null ) + { + throw new IllegalArgumentException( "writer, outputStream or path must be non null" ); + } + try + { + if ( writer != null ) + { + new MavenXpp3WriterEx().write( writer, content ); + } + else if ( outputStream != null ) + { + new MavenXpp3WriterEx().write( outputStream, content ); + } + else + { + try ( OutputStream os = Files.newOutputStream( path ) ) + { + new MavenXpp3WriterEx().write( outputStream, content ); + } + } + } + catch ( Exception e ) + { + throw new XmlWriterException( "Unable to write model", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java new file mode 100644 index 000000000000..c0ec2bebf18a --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java @@ -0,0 +1,73 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Optional; + +import org.apache.maven.api.MojoExecution; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.Xpp3Dom; + +public class DefaultMojoExecution + implements MojoExecution +{ + private final org.apache.maven.plugin.MojoExecution delegate; + + public DefaultMojoExecution( org.apache.maven.plugin.MojoExecution delegate ) + { + this.delegate = delegate; + } + + public org.apache.maven.plugin.MojoExecution getDelegate() + { + return delegate; + } + + @Override + public Plugin getPlugin() + { + return delegate.getPlugin().getDelegate(); + } + + @Override + public String getExecutionId() + { + return delegate.getExecutionId(); + } + + @Override + public String getGoal() + { + return delegate.getGoal(); + } + + @Override + public Optional getConfiguration() + { + return Optional.of( delegate.getConfiguration() ).map( Xpp3Dom::getDom ); + } + + @Override + public String toString() + { + return delegate.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java new file mode 100644 index 000000000000..787d76c22f78 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java @@ -0,0 +1,173 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Nonnull; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.transformer.ConflictResolver; + +public class DefaultNode extends AbstractNode +{ + + protected final @Nonnull AbstractSession session; + protected final @Nonnull org.eclipse.aether.graph.DependencyNode node; + protected final boolean verbose; + + public DefaultNode( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.graph.DependencyNode node, + boolean verbose ) + { + this.session = session; + this.node = node; + this.verbose = verbose; + } + + @Override + DependencyNode getDependencyNode() + { + return node; + } + + @Override + public Dependency getDependency() + { + return node.getDependency() != null ? session.getDependency( node.getDependency() ) : null; + } + + @Override + public List getChildren() + { + return new MappedList<>( node.getChildren(), n -> session.getNode( n, verbose ) ); + } + + @Override + public List getRemoteRepositories() + { + return new MappedList<>( node.getRepositories(), session::getRemoteRepository ); + } + + @Override + public Optional getRepository() + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public String asString() + { + String nodeString = super.asString(); + + if ( !verbose ) + { + return nodeString; + } + + org.eclipse.aether.graph.DependencyNode node = getDependencyNode(); + + List details = new ArrayList<>(); + + org.eclipse.aether.graph.DependencyNode winner = + (org.eclipse.aether.graph.DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER ); + String winnerVersion = winner != null ? winner.getArtifact().getBaseVersion() : null; + boolean included = ( winnerVersion == null ); + + String preManagedVersion = DependencyManagerUtils.getPremanagedVersion( node ); + if ( preManagedVersion != null ) + { + details.add( "version managed from " + preManagedVersion ); + } + + String preManagedScope = DependencyManagerUtils.getPremanagedScope( node ); + if ( preManagedScope != null ) + { + details.add( "scope managed from " + preManagedScope ); + } + + String originalScope = (String) node.getData().get( ConflictResolver.NODE_DATA_ORIGINAL_SCOPE ); + if ( originalScope != null && !originalScope.equals( node.getDependency().getScope() ) ) + { + details.add( "scope updated from " + originalScope ); + } + + if ( !included ) + { + if ( Objects.equals( winnerVersion, node.getArtifact().getVersion() ) ) + { + details.add( "omitted for duplicate" ); + } + else + { + details.add( "omitted for conflict with " + winnerVersion ); + } + } + + StringBuilder buffer = new StringBuilder(); + if ( included ) + { + buffer.append( nodeString ); + if ( !details.isEmpty() ) + { + buffer.append( " (" ); + join( buffer, details, "; " ); + buffer.append( ")" ); + } + } + else + { + buffer.append( "(" ); + buffer.append( nodeString ); + if ( !details.isEmpty() ) + { + buffer.append( " - " ); + join( buffer, details, "; " ); + } + buffer.append( ")" ); + } + return buffer.toString(); + } + + private static void join( StringBuilder buffer, List details, String separator ) + { + boolean first = true; + for ( String detail : details ) + { + if ( first ) + { + first = false; + } + else + { + buffer.append( separator ); + } + buffer.append( detail ); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java new file mode 100644 index 000000000000..50e083dd0b6c --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -0,0 +1,250 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Scope; +import org.apache.maven.api.Type; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Project; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.TypeRegistry; +import org.apache.maven.project.MavenProject; + +public class DefaultProject implements Project +{ + + private final AbstractSession session; + private final MavenProject project; + + public DefaultProject( AbstractSession session, MavenProject project ) + { + this.session = session; + this.project = project; + } + + public AbstractSession getSession() + { + return session; + } + + public MavenProject getProject() + { + return project; + } + + @Nonnull + @Override + public String getGroupId() + { + return project.getGroupId(); + } + + @Nonnull + @Override + public String getArtifactId() + { + return project.getArtifactId(); + } + + @Nonnull + @Override + public String getVersion() + { + return project.getVersion(); + } + + @Nonnull + @Override + public Artifact getArtifact() + { + org.eclipse.aether.artifact.Artifact resolverArtifact = RepositoryUtils.toArtifact( project.getArtifact() ); + Artifact artifact = session.getArtifact( resolverArtifact ); + Path path = resolverArtifact.getFile() != null ? resolverArtifact.getFile().toPath() : null; + session.getService( ArtifactManager.class ).setPath( artifact, path ); + return artifact; + } + + @Nonnull + @Override + public String getPackaging() + { + return project.getPackaging(); + } + + @Nonnull + @Override + public Model getModel() + { + return project.getModel().getDelegate(); + } + + @Nonnull + @Override + public Optional getPomPath() + { + File file = project.getFile(); + return Optional.ofNullable( file ).map( File::toPath ); + } + + @Nonnull + @Override + public List getDependencies() + { + return new MappedList<>( getModel().getDependencies(), this::toDependency ); + } + + @Nonnull + @Override + public List getManagedDependencies() + { + DependencyManagement dependencyManagement = getModel().getDependencyManagement(); + if ( dependencyManagement != null ) + { + return new MappedList<>( dependencyManagement.getDependencies(), this::toDependency ); + } + return Collections.emptyList(); + } + + @Override + public boolean isExecutionRoot() + { + return project.isExecutionRoot(); + } + + @Override + public Optional getParent() + { + MavenProject parent = project.getParent(); + return parent != null ? Optional.of( session.getProject( parent ) ) : Optional.empty(); + } + + @Override + public List getRemoteProjectRepositories() + { + return new MappedList<>( project.getRemoteProjectRepositories(), session::getRemoteRepository ); + } + + @Override + public List getRemotePluginRepositories() + { + return new MappedList<>( project.getRemotePluginRepositories(), session::getRemoteRepository ); + } + + @Nonnull + private DependencyCoordinate toDependency( org.apache.maven.api.model.Dependency dependency ) + { + return new DependencyCoordinate() + { + @Override + public String getGroupId() + { + return dependency.getGroupId(); + } + + @Override + public String getArtifactId() + { + return dependency.getArtifactId(); + } + + @Override + public String getClassifier() + { + return dependency.getClassifier(); + } + + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( dependency.getVersion() ); + } + + @Override + public String getExtension() + { + return getType().getExtension(); + } + + @Override + public Type getType() + { + String type = dependency.getType(); + return session.getService( TypeRegistry.class ).getType( type ); + } + + @Nonnull + @Override + public Scope getScope() + { + return Scope.get( dependency.getScope() ); + } + + @Override + public Boolean getOptional() + { + return dependency.isOptional(); + } + + @Nonnull + @Override + public Collection getExclusions() + { + return new MappedCollection<>( dependency.getExclusions(), this::toExclusion ); + } + + private Exclusion toExclusion( org.apache.maven.api.model.Exclusion exclusion ) + { + return new Exclusion() + { + @Nullable + @Override + public String getGroupId() + { + return exclusion.getGroupId(); + } + + @Nullable + @Override + public String getArtifactId() + { + return exclusion.getArtifactId(); + } + }; + } + }; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java new file mode 100644 index 000000000000..d9911c20148d --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -0,0 +1,267 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.DependencyCollectorResult; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectBuilderException; +import org.apache.maven.api.services.ProjectBuilderProblem; +import org.apache.maven.api.services.ProjectBuilderProblemSeverity; +import org.apache.maven.api.services.ProjectBuilderRequest; +import org.apache.maven.api.services.ProjectBuilderResult; +import org.apache.maven.api.services.ProjectBuilderSource; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.building.ModelProblem; +import org.apache.maven.model.building.ModelSource; +import org.apache.maven.project.DefaultProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingResult; + +public class DefaultProjectBuilder implements ProjectBuilder +{ + + private final org.apache.maven.project.ProjectBuilder builder; + + @Inject + public DefaultProjectBuilder( org.apache.maven.project.ProjectBuilder builder ) + { + this.builder = builder; + } + + @SuppressWarnings( "MethodLength" ) + @Nonnull + @Override + public ProjectBuilderResult build( ProjectBuilderRequest request ) + throws ProjectBuilderException, IllegalArgumentException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + try + { + List repositories = + session.toArtifactRepositories( session.getRemoteRepositories() ); + ProjectBuildingRequest req = new DefaultProjectBuildingRequest() + .setRepositorySession( session.getSession() ) + .setRemoteRepositories( repositories ) + .setPluginArtifactRepositories( repositories ) + .setProcessPlugins( request.isProcessPlugins() ); + ProjectBuildingResult res; + if ( request.getPath().isPresent() ) + { + Path path = request.getPath().get(); + res = builder.build( path.toFile(), req ); + } + else if ( request.getSource().isPresent() ) + { + ProjectBuilderSource source = request.getSource().get(); + ModelSource modelSource = new ModelSource() + { + @Override + public InputStream getInputStream() throws IOException + { + return source.getInputStream(); + } + + @Override + public String getLocation() + { + return source.getLocation(); + } + }; + res = builder.build( modelSource, req ); + } + else if ( request.getArtifact().isPresent() ) + { + Artifact a = request.getArtifact().get(); + org.eclipse.aether.artifact.Artifact aetherArtifact = session.toArtifact( a ); + org.apache.maven.artifact.Artifact artifact = RepositoryUtils.toArtifact( aetherArtifact ); + res = builder.build( artifact, request.isAllowStubModel(), req ); + } + else if ( request.getCoordinate().isPresent() ) + { + ArtifactCoordinate c = request.getCoordinate().get(); + org.apache.maven.artifact.Artifact artifact = new DefaultArtifact( + c.getGroupId(), c.getArtifactId(), c.getVersion().asString(), null, + c.getExtension(), c.getClassifier(), null ); + res = builder.build( artifact, request.isAllowStubModel(), req ); + } + else + { + throw new IllegalArgumentException( "Invalid request" ); + } + return new ProjectBuilderResult() + { + @Nonnull + @Override + public String getProjectId() + { + return res.getProjectId(); + } + + @Nonnull + @Override + public Optional getPomFile() + { + return Optional.ofNullable( res.getPomFile() ).map( File::toPath ); + } + + @Nonnull + @Override + public Optional getProject() + { + return Optional.ofNullable( res.getProject() ) + .map( session::getProject ); + } + + @Nonnull + @Override + public Collection getProblems() + { + return new MappedCollection<>( res.getProblems(), this::toProblem ); + } + + private ProjectBuilderProblem toProblem( ModelProblem problem ) + { + return new ProjectBuilderProblem() + { + @Override + public String getSource() + { + return problem.getSource(); + } + + @Override + public int getLineNumber() + { + return problem.getLineNumber(); + } + + @Override + public int getColumnNumber() + { + return problem.getColumnNumber(); + } + + @Override + public String getLocation() + { + StringBuilder buffer = new StringBuilder( 256 ); + + if ( getSource().length() > 0 ) + { + if ( buffer.length() > 0 ) + { + buffer.append( ", " ); + } + buffer.append( getSource() ); + } + + if ( getLineNumber() > 0 ) + { + if ( buffer.length() > 0 ) + { + buffer.append( ", " ); + } + buffer.append( "line " ).append( getLineNumber() ); + } + + if ( getColumnNumber() > 0 ) + { + if ( buffer.length() > 0 ) + { + buffer.append( ", " ); + } + buffer.append( "column " ).append( getColumnNumber() ); + } + + return buffer.toString(); + } + + @Override + public Exception getException() + { + return problem.getException(); + } + + @Override + public String getMessage() + { + return problem.getMessage(); + } + + @Override + public ProjectBuilderProblemSeverity getSeverity() + { + return ProjectBuilderProblemSeverity.valueOf( problem.getSeverity().name() ); + } + }; + } + + @Nonnull + @Override + public Optional getDependencyResolverResult() + { + return Optional.ofNullable( res.getDependencyResolutionResult() ) + .map( r -> new DependencyCollectorResult() + { + @Override + public List getExceptions() + { + return r.getCollectionErrors(); + } + + @Override + public Node getRoot() + { + return session.getNode( r.getDependencyGraph() ); + } + +// @Override +// public List getArtifactResults() +// { +// return Collections.emptyList(); +// } + } ); + } + }; + } + catch ( ProjectBuildingException e ) + { + throw new ProjectBuilderException( "Unable to build project", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java new file mode 100644 index 000000000000..4a5e62218180 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -0,0 +1,177 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.ResolutionScope; +import org.apache.maven.api.Scope; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.MavenException; +import org.apache.maven.api.services.ProjectManager; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; + +public class DefaultProjectManager implements ProjectManager +{ + + private final Session session; + private final ArtifactManager artifactManager; + private final PlexusContainer container; + + public DefaultProjectManager( Session session, + ArtifactManager artifactManager, + PlexusContainer container ) + { + this.session = session; + this.artifactManager = artifactManager; + this.container = container; + } + + @Nonnull + @Override + public Optional getPath( Project project ) + { + // TODO: apiv4 + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Nonnull + @Override + public Collection getAttachedArtifacts( Project project ) + { + AbstractSession session = ( (DefaultProject ) project ).getSession(); + Collection attached = getMavenProject( project ).getAttachedArtifacts().stream() + .map( RepositoryUtils::toArtifact ) + .map( session::getArtifact ) + .collect( Collectors.toList() ); + return Collections.unmodifiableCollection( attached ); + } + + @Override + public void attachArtifact( Project project, Artifact artifact, Path path ) + { + getMavenProject( project ).addAttachedArtifact( + RepositoryUtils.toArtifact( ( ( DefaultProject ) project ).getSession().toArtifact( artifact ) ) ); + artifactManager.setPath( artifact, path ); + } + + @Override + public List getCompileSourceRoots( Project project ) + { + List roots = getMavenProject( project ).getCompileSourceRoots(); + return Collections.unmodifiableList( roots ); + } + + @Override + public void addCompileSourceRoot( Project project, String sourceRoot ) + { + List roots = getMavenProject( project ).getCompileSourceRoots(); + roots.add( sourceRoot ); + } + + @Override + public List getTestCompileSourceRoots( Project project ) + { + List roots = getMavenProject( project ).getTestCompileSourceRoots(); + return Collections.unmodifiableList( roots ); + } + + @Override + public void addTestCompileSourceRoot( Project project, String sourceRoot ) + { + List roots = getMavenProject( project ).getTestCompileSourceRoots(); + roots.add( sourceRoot ); + } + + @Override + public List getRepositories( Project project ) + { + // TODO: apiv4 + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public List getResolvedDependencies( Project project, ResolutionScope scope ) + { + Collection toResolve = toScopes( scope ); + try + { + LifecycleDependencyResolver lifecycleDependencyResolver = + container.lookup( LifecycleDependencyResolver.class ); + Set artifacts = lifecycleDependencyResolver.resolveProjectArtifacts( + getMavenProject( project ), + toResolve, + toResolve, + ( ( DefaultSession ) session ).getMavenSession(), + false, + Collections.emptySet() + ); + return artifacts.stream() + .map( RepositoryUtils::toArtifact ) + .map( ( ( DefaultSession ) session )::getArtifact ) + .collect( Collectors.toList() ); + } + catch ( LifecycleExecutionException | ComponentLookupException e ) + { + throw new MavenException( "Unable to resolve project dependencies", e ); + } + } + + @Override + public Node getCollectedDependencies( Project project, ResolutionScope scope ) + { + // TODO: apiv4 + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public void setProperty( Project project, String key, String value ) + { + getMavenProject( project ).getProperties().setProperty( key, value ); + } + + private MavenProject getMavenProject( Project project ) + { + return ( ( DefaultProject ) project ).getProject(); + } + + private Collection toScopes( ResolutionScope scope ) + { + return scope.scopes().stream().map( Scope::id ).collect( Collectors.toList() ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java new file mode 100644 index 000000000000..e1e87f3e088c --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java @@ -0,0 +1,87 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.lang.reflect.Method; +import java.util.List; + +import org.apache.maven.api.services.Prompter; +import org.apache.maven.api.services.PrompterException; +import org.codehaus.plexus.PlexusContainer; + +public class DefaultPrompter implements Prompter +{ + + private static final String PROMPTER_CLASS = "org.codehaus.plexus.components.interactivity.Prompter"; + private final PlexusContainer container; + + public DefaultPrompter( PlexusContainer container ) + { + this.container = container; + } + + @Override + public String prompt( String message, List possibleValues, String defaultReply ) throws PrompterException + { + try + { + Class clazz = container.getContainerRealm().loadClass( PROMPTER_CLASS ); + Object instance = container.lookup( clazz ); + Method method = clazz.getMethod( "prompt", String.class, List.class, String.class ); + return (String) method.invoke( instance, message, possibleValues, defaultReply ); + } + catch ( Exception e ) + { + throw new PrompterException( "Unable to call prompter", e ); + } + } + + @Override + public String promptForPassword( String message ) throws PrompterException + { + try + { + Class clazz = container.getContainerRealm().loadClass( PROMPTER_CLASS ); + Object instance = container.lookup( clazz ); + Method method = clazz.getMethod( "promptForPassword", String.class ); + return (String) method.invoke( instance, message ); + } + catch ( Exception e ) + { + throw new PrompterException( "Unable to call prompter", e ); + } + } + + @Override + public void showMessage( String message ) throws PrompterException + { + try + { + Class clazz = container.getContainerRealm().loadClass( PROMPTER_CLASS ); + Object instance = container.lookup( clazz ); + Method method = clazz.getMethod( "showMessage", String.class ); + method.invoke( instance, message ); + } + catch ( Exception e ) + { + throw new PrompterException( "Unable to call prompter", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java new file mode 100644 index 000000000000..e56d54280ad9 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java @@ -0,0 +1,67 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.RemoteRepository; + +public class DefaultRemoteRepository implements RemoteRepository +{ + private final org.eclipse.aether.repository.RemoteRepository repository; + + public DefaultRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository ) + { + this.repository = repository; + } + + public org.eclipse.aether.repository.RemoteRepository getRepository() + { + return repository; + } + + @Nonnull + @Override + public String getId() + { + return repository.getId(); + } + + @Nonnull + @Override + public String getType() + { + return repository.getContentType(); + } + + @Nonnull + @Override + public String getUrl() + { + return repository.getUrl(); + } + + @Nonnull + @Override + public String getProtocol() + { + return repository.getProtocol(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java new file mode 100644 index 000000000000..c61774c5f016 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java @@ -0,0 +1,88 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.model.Repository; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.RepositoryPolicy; + +public class DefaultRepositoryFactory implements RepositoryFactory +{ + + private final RepositorySystem repositorySystem; + + public DefaultRepositoryFactory( RepositorySystem repositorySystem ) + { + this.repositorySystem = repositorySystem; + } + + @Override + public LocalRepository createLocal( Path path ) + { + return new DefaultLocalRepository( new org.eclipse.aether.repository.LocalRepository( path.toFile() ) ); + } + + @Override + public RemoteRepository createRemote( String id, String url ) + { + return new DefaultRemoteRepository( + new org.eclipse.aether.repository.RemoteRepository.Builder( id, "default", url ) + .build() ); + } + + @Override + public RemoteRepository createRemote( Repository repository ) + throws IllegalArgumentException + { + return new DefaultRemoteRepository( + new org.eclipse.aether.repository.RemoteRepository.Builder( + repository.getId(), repository.getLayout(), repository.getUrl() ) + .setReleasePolicy( buildRepositoryPolicy( repository.getReleases() ) ) + .setSnapshotPolicy( buildRepositoryPolicy( repository.getSnapshots() ) ) + .build() ); + } + + public static org.eclipse.aether.repository.RepositoryPolicy buildRepositoryPolicy( + org.apache.maven.api.model.RepositoryPolicy policy ) + { + boolean enabled = true; + String updatePolicy = RepositoryPolicy.UPDATE_POLICY_DAILY; + String checksumPolicy = RepositoryPolicy.CHECKSUM_POLICY_FAIL; + if ( policy != null ) + { + enabled = policy.isEnabled(); + if ( policy.getUpdatePolicy() != null ) + { + updatePolicy = policy.getUpdatePolicy(); + } + if ( policy.getChecksumPolicy() != null ) + { + checksumPolicy = policy.getChecksumPolicy(); + } + } + return new org.eclipse.aether.repository.RepositoryPolicy( + enabled, updatePolicy, checksumPolicy ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java new file mode 100644 index 000000000000..2b4ed18ccd94 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -0,0 +1,397 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Properties; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.SessionData; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactCoordinateFactory; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCoordinateFactory; +import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.Lookup; +import org.apache.maven.api.services.MavenException; +import org.apache.maven.api.services.MessageBuilderFactory; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectManager; +import org.apache.maven.api.services.Prompter; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.ToolchainManager; +import org.apache.maven.api.services.TypeRegistry; +import org.apache.maven.api.services.VersionParser; +import org.apache.maven.api.services.xml.ModelXmlFactory; +import org.apache.maven.api.services.xml.SettingsXmlFactory; +import org.apache.maven.api.services.xml.ToolchainsXmlFactory; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.rtinfo.RuntimeInformation; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultSession extends AbstractSession +{ + + private final MavenSession mavenSession; + private final RepositorySystemSession session; + private final RepositorySystem repositorySystem; + private final List repositories; + private final org.apache.maven.project.ProjectBuilder projectBuilder; + private final MavenRepositorySystem mavenRepositorySystem; + private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + private final PlexusContainer container; + private final MojoExecutionScope mojoExecutionScope; + private final RuntimeInformation runtimeInformation; + private final ArtifactHandlerManager artifactHandlerManager; + private final Map, Service> services = new HashMap<>(); + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + public DefaultSession( @Nonnull MavenSession session, + @Nonnull RepositorySystem repositorySystem, + @Nullable List repositories, + @Nonnull org.apache.maven.project.ProjectBuilder projectBuilder, + @Nonnull MavenRepositorySystem mavenRepositorySystem, + @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate, + @Nonnull PlexusContainer container, + @Nonnull MojoExecutionScope mojoExecutionScope, + @Nonnull RuntimeInformation runtimeInformation, + @Nonnull ArtifactHandlerManager artifactHandlerManager ) + { + this.mavenSession = nonNull( session ); + this.session = mavenSession.getRepositorySession(); + this.repositorySystem = nonNull( repositorySystem ); + this.repositories = repositories != null + ? repositories + : mavenSession.getRequest().getRemoteRepositories().stream() + .map( RepositoryUtils::toRepo ).map( this::getRemoteRepository ).collect( Collectors.toList() ); + this.projectBuilder = projectBuilder; + this.mavenRepositorySystem = mavenRepositorySystem; + this.toolchainManagerPrivate = toolchainManagerPrivate; + this.container = container; + this.mojoExecutionScope = mojoExecutionScope; + this.runtimeInformation = runtimeInformation; + this.artifactHandlerManager = artifactHandlerManager; + + ArtifactManager artifactManager = new DefaultArtifactManager( this ); + ProjectManager projectManager = new DefaultProjectManager( this, artifactManager, container ); + + services.put( ArtifactFactory.class, new DefaultArtifactFactory() ); + services.put( ArtifactResolver.class, new DefaultArtifactResolver( repositorySystem ) ); + services.put( ArtifactDeployer.class, new DefaultArtifactDeployer( repositorySystem ) ); + services.put( ArtifactInstaller.class, new DefaultArtifactInstaller( repositorySystem ) ); + services.put( ArtifactManager.class, artifactManager ); + services.put( DependencyCoordinateFactory.class, new DefaultDependencyCoordinateFactory() ); + services.put( DependencyCollector.class, new DefaultDependencyCollector( repositorySystem ) ); + services.put( ProjectBuilder.class, new DefaultProjectBuilder( projectBuilder ) ); + services.put( ProjectManager.class, projectManager ); + services.put( LocalRepositoryManager.class, new DefaultLocalRepositoryManager() ); + services.put( RepositoryFactory.class, new DefaultRepositoryFactory( repositorySystem ) ); + services.put( ToolchainManager.class, new DefaultToolchainManager( toolchainManagerPrivate ) ); + services.put( ModelXmlFactory.class, new DefaultModelXmlFactory() ); + services.put( SettingsXmlFactory.class, new DefaultSettingsXmlFactory() ); + services.put( ToolchainsXmlFactory.class, new DefaultToolchainsXmlFactory() ); + services.put( Prompter.class, new DefaultPrompter( container ) ); + services.put( MessageBuilderFactory.class, new DefaultMessageBuilderFactory() ); + services.put( VersionParser.class, new DefaultVersionParser() ); + services.put( ArtifactCoordinateFactory.class, new DefaultArtifactCoordinateFactory() ); + services.put( TypeRegistry.class, new DefaultTypeRegistry( artifactHandlerManager ) ); + services.put( Lookup.class, new DefaultLookup( container ) ); + } + + public MavenSession getMavenSession() + { + return mavenSession; + } + + @Nonnull + @Override + public LocalRepository getLocalRepository() + { + return new DefaultLocalRepository( session.getLocalRepository() ); + } + + @Nonnull + @Override + public List getRemoteRepositories() + { + return Collections.unmodifiableList( repositories ); + } + + @Nonnull + @Override + public Settings getSettings() + { + return mavenSession.getSettings().getDelegate(); + } + + @Nonnull + @Override + public Properties getUserProperties() + { + return mavenSession.getUserProperties(); + } + + @Nonnull + @Override + public Properties getSystemProperties() + { + return mavenSession.getSystemProperties(); + } + + @Nonnull + @Override + public String getMavenVersion() + { + return runtimeInformation.getMavenVersion(); + } + + @Override + public int getDegreeOfConcurrency() + { + return mavenSession.getRequest().getDegreeOfConcurrency(); + } + + @Nonnull + @Override + public Instant getStartTime() + { + return mavenSession.getStartTime().toInstant(); + } + + @Nonnull + @Override + public Path getMultiModuleProjectDirectory() + { + return mavenSession.getRequest().getMultiModuleProjectDirectory().toPath(); + } + + @Nonnull + @Override + public Path getExecutionRootDirectory() + { + return Paths.get( mavenSession.getRequest().getBaseDirectory() ); + } + + @Nonnull + @Override + public List getProjects() + { + return getProjects( mavenSession.getProjects() ); + } + + @Nonnull + @Override + public Map getPluginContext( Project project ) + { + nonNull( project, "project" ); + try + { + MojoExecution mojoExecution = container.lookup( MojoExecution.class ); + MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); + PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor(); + return mavenSession.getPluginContext( pluginDescriptor, ( ( DefaultProject ) project ).getProject() ); + } + catch ( ComponentLookupException e ) + { + throw new MavenException( "The PluginContext is only available during a mojo execution", e ); + } + } + + @Nonnull + @Override + public SessionData getData() + { + org.eclipse.aether.SessionData data = session.getData(); + return new SessionData() + { + @Override + public void set( @Nonnull Object key, @Nullable Object value ) + { + data.set( key, value ); + } + + @Override + public boolean set( @Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue ) + { + return data.set( key, oldValue, newValue ); + } + + @Nullable + @Override + public Object get( @Nonnull Object key ) + { + return data.get( key ); + } + + @Nullable + @Override + public Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier supplier ) + { + return data.computeIfAbsent( key, supplier ); + } + }; + } + + @Nonnull + @Override + public Session withLocalRepository( @Nonnull LocalRepository localRepository ) + { + nonNull( localRepository, "localRepository" ); + if ( session.getLocalRepository() != null + && Objects.equals( session.getLocalRepository().getBasedir().toPath(), + localRepository.getPath() ) ) + { + return this; + } + org.eclipse.aether.repository.LocalRepository repository = toRepository( localRepository ); + org.eclipse.aether.repository.LocalRepositoryManager localRepositoryManager + = repositorySystem.newLocalRepositoryManager( session, repository ); + + RepositorySystemSession repoSession = new DefaultRepositorySystemSession( session ) + .setLocalRepositoryManager( localRepositoryManager ); + MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, + mavenSession.getRequest(), mavenSession.getResult() ); + return new DefaultSession( newSession, repositorySystem, repositories, projectBuilder, mavenRepositorySystem, + toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation, artifactHandlerManager ); + } + + @Nonnull + @Override + public Session withRemoteRepositories( @Nonnull List repositories ) + { + return new DefaultSession( mavenSession, repositorySystem, repositories, projectBuilder, mavenRepositorySystem, + toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation, artifactHandlerManager ); + } + + @Nonnull + @Override + @SuppressWarnings( "unchecked" ) + public T getService( Class clazz ) throws NoSuchElementException + { + T t = (T) services.get( clazz ); + if ( t == null ) + { + throw new NoSuchElementException( clazz.getName() ); + } + return t; + } + + @Nonnull + public RepositorySystemSession getSession() + { + return session; + } + + @Nonnull + public RepositorySystem getRepositorySystem() + { + return repositorySystem; + } + + public ArtifactRepository toArtifactRepository( RemoteRepository repository ) + { + if ( repository instanceof DefaultRemoteRepository ) + { + org.eclipse.aether.repository.RemoteRepository rr + = ( (DefaultRemoteRepository) repository ).getRepository(); + + try + { + return mavenRepositorySystem.createRepository( + rr.getUrl(), + rr.getId(), + rr.getPolicy( false ).isEnabled(), + rr.getPolicy( false ).getUpdatePolicy(), + rr.getPolicy( true ).isEnabled(), + rr.getPolicy( true ).getUpdatePolicy(), + rr.getPolicy( false ).getChecksumPolicy() + + ); + } + catch ( Exception e ) + { + throw new RuntimeException( "Unable to create repository", e ); + } + } + else + { + // TODO + throw new UnsupportedOperationException( "Not yet implemented" ); + } + } + + public org.eclipse.aether.graph.Dependency toDependency( DependencyCoordinate dependency ) + { + if ( dependency instanceof DefaultDependencyCoordinate ) + { + return ( (DefaultDependencyCoordinate) dependency ).getDependency(); + } + else + { + return new org.eclipse.aether.graph.Dependency( + new org.eclipse.aether.artifact.DefaultArtifact( + dependency.getGroupId(), + dependency.getArtifactId(), + dependency.getClassifier(), + dependency.getType().getExtension(), + dependency.getVersion().toString(), + null ), + dependency.getScope().id() ); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java new file mode 100644 index 000000000000..4816006abb71 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -0,0 +1,85 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.maven.api.Session; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.rtinfo.RuntimeInformation; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.PlexusContainer; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.SessionData; + +@Singleton +@Named +public class DefaultSessionFactory +{ + private final RepositorySystem repositorySystem; + private final org.apache.maven.project.ProjectBuilder projectBuilder; + private final MavenRepositorySystem mavenRepositorySystem; + private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + private final PlexusContainer plexusContainer; + private final MojoExecutionScope mojoExecutionScope; + private final RuntimeInformation runtimeInformation; + private final ArtifactHandlerManager artifactHandlerManager; + + @Inject + @SuppressWarnings( "checkstyle:ParameterNumber" ) + public DefaultSessionFactory( RepositorySystem repositorySystem, + ProjectBuilder projectBuilder, + MavenRepositorySystem mavenRepositorySystem, + DefaultToolchainManagerPrivate toolchainManagerPrivate, + PlexusContainer plexusContainer, + MojoExecutionScope mojoExecutionScope, + RuntimeInformation runtimeInformation, + ArtifactHandlerManager artifactHandlerManager ) + { + this.repositorySystem = repositorySystem; + this.projectBuilder = projectBuilder; + this.mavenRepositorySystem = mavenRepositorySystem; + this.toolchainManagerPrivate = toolchainManagerPrivate; + this.plexusContainer = plexusContainer; + this.mojoExecutionScope = mojoExecutionScope; + this.runtimeInformation = runtimeInformation; + this.artifactHandlerManager = artifactHandlerManager; + } + + public Session getSession( MavenSession mavenSession ) + { + SessionData data = mavenSession.getRepositorySession().getData(); + return ( Session ) data.computeIfAbsent( DefaultSession.class, () -> newSession( mavenSession ) ); + } + + private Session newSession( MavenSession mavenSession ) + { + return new DefaultSession( + mavenSession, repositorySystem, null, projectBuilder, mavenRepositorySystem, + toolchainManagerPrivate, plexusContainer, mojoExecutionScope, runtimeInformation, + artifactHandlerManager ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java new file mode 100644 index 000000000000..ee0329fcbe39 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java @@ -0,0 +1,103 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Objects; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.xml.SettingsXmlFactory; +import org.apache.maven.api.services.xml.XmlReaderException; +import org.apache.maven.api.services.xml.XmlReaderRequest; +import org.apache.maven.api.services.xml.XmlWriterException; +import org.apache.maven.api.services.xml.XmlWriterRequest; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.v4.SettingsXpp3Reader; +import org.apache.maven.settings.v4.SettingsXpp3Writer; + +public class DefaultSettingsXmlFactory + implements SettingsXmlFactory +{ + @Override + public Settings read( @Nonnull XmlReaderRequest request ) throws XmlReaderException + { + Objects.requireNonNull( request, "request can not be null" ); + Reader reader = request.getReader(); + InputStream inputStream = request.getInputStream(); + if ( reader == null && inputStream == null ) + { + throw new IllegalArgumentException( "reader or inputStream must be non null" ); + } + try + { + InputSource source = null; + if ( request.getModelId() != null || request.getLocation() != null ) + { + source = new InputSource( request.getModelId(), request.getLocation() ); + } + SettingsXpp3Reader xml = new SettingsXpp3Reader(); + xml.setAddDefaultEntities( request.isAddDefaultEntities() ); + if ( reader != null ) + { + return xml.read( reader, request.isStrict() ); + } + else + { + return xml.read( inputStream, request.isStrict() ); + } + } + catch ( Exception e ) + { + throw new XmlReaderException( "Unable to read settings", e ); + } + } + + @Override + public void write( XmlWriterRequest request ) throws XmlWriterException + { + Objects.requireNonNull( request, "request can not be null" ); + Settings content = Objects.requireNonNull( request.getContent(), "content can not be null" ); + OutputStream outputStream = request.getOutputStream(); + Writer writer = request.getWriter(); + if ( writer == null && outputStream == null ) + { + throw new IllegalArgumentException( "writer or outputStream must be non null" ); + } + try + { + if ( writer != null ) + { + new SettingsXpp3Writer().write( writer, content ); + } + else + { + new SettingsXpp3Writer().write( outputStream, content ); + } + } + catch ( Exception e ) + { + throw new XmlWriterException( "Unable to write settings", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java new file mode 100644 index 000000000000..f40de6585581 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java @@ -0,0 +1,122 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Toolchain; +import org.apache.maven.api.services.ToolchainManager; +import org.apache.maven.api.services.ToolchainManagerException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.apache.maven.toolchain.MisconfiguredToolchainException; +import org.apache.maven.toolchain.ToolchainPrivate; + +public class DefaultToolchainManager implements ToolchainManager +{ + private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + + public DefaultToolchainManager( DefaultToolchainManagerPrivate toolchainManagerPrivate ) + { + this.toolchainManagerPrivate = toolchainManagerPrivate; + } + + @Override + public List getToolchains( Session session, String type, Map requirements ) + throws ToolchainManagerException + { + MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); + List toolchains = + toolchainManagerPrivate.getToolchains( s, type, requirements ); + return new MappedList<>( toolchains, this::toToolchain ); + } + + @Override + public Optional getToolchainFromBuildContext( Session session, String type ) + throws ToolchainManagerException + { + MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); + return Optional.ofNullable( toolchainManagerPrivate.getToolchainFromBuildContext( type, s ) ) + .map( this::toToolchain ); + } + + @Override + public List getToolchainsForType( Session session, String type ) + throws ToolchainManagerException + { + try + { + MavenSession s = ( (DefaultSession) session ).getMavenSession(); + ToolchainPrivate[] toolchains = toolchainManagerPrivate.getToolchainsForType( type, s ); + return new MappedList<>( Arrays.asList( toolchains ), this::toToolchain ); + } + catch ( MisconfiguredToolchainException e ) + { + throw new ToolchainManagerException( "Unable to get toochains for type " + type, e ); + } + } + + @Override + public void storeToolchainToBuildContext( Session session, Toolchain toolchain ) + throws ToolchainManagerException + { + MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); + org.apache.maven.toolchain.ToolchainPrivate tc = + (org.apache.maven.toolchain.ToolchainPrivate) ( (ToolchainWrapper) toolchain ).toolchain; + toolchainManagerPrivate.storeToolchainToBuildContext( tc, s ); + } + + private Toolchain toToolchain( org.apache.maven.toolchain.Toolchain toolchain ) + { + return new ToolchainWrapper( toolchain ); + } + + private static class ToolchainWrapper implements Toolchain + { + private final org.apache.maven.toolchain.Toolchain toolchain; + + ToolchainWrapper( org.apache.maven.toolchain.Toolchain toolchain ) + { + this.toolchain = toolchain; + } + + @Override + public String getType() + { + return toolchain.getType(); + } + + @Override + public String findTool( String toolName ) + { + return toolchain.findTool( toolName ); + } + + @Override + public boolean matchesRequirements( Map requirements ) + { + return ( (ToolchainPrivate) toolchain ).matchesRequirements( requirements ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java new file mode 100644 index 000000000000..33e6db4a7820 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java @@ -0,0 +1,103 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Objects; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.xml.ToolchainsXmlFactory; +import org.apache.maven.api.services.xml.XmlReaderException; +import org.apache.maven.api.services.xml.XmlReaderRequest; +import org.apache.maven.api.services.xml.XmlWriterException; +import org.apache.maven.api.services.xml.XmlWriterRequest; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; + +public class DefaultToolchainsXmlFactory + implements ToolchainsXmlFactory +{ + @Override + public PersistedToolchains read( @Nonnull XmlReaderRequest request ) throws XmlReaderException + { + Objects.requireNonNull( request, "request can not be null" ); + Reader reader = request.getReader(); + InputStream inputStream = request.getInputStream(); + if ( reader == null && inputStream == null ) + { + throw new IllegalArgumentException( "reader or inputStream must be non null" ); + } + try + { + InputSource source = null; + if ( request.getModelId() != null || request.getLocation() != null ) + { + source = new InputSource( request.getModelId(), request.getLocation() ); + } + MavenToolchainsXpp3Reader xml = new MavenToolchainsXpp3Reader(); + xml.setAddDefaultEntities( request.isAddDefaultEntities() ); + if ( reader != null ) + { + return xml.read( reader, request.isStrict() ); + } + else + { + return xml.read( inputStream, request.isStrict() ); + } + } + catch ( Exception e ) + { + throw new XmlReaderException( "Unable to read toolchains", e ); + } + } + + @Override + public void write( XmlWriterRequest request ) throws XmlWriterException + { + Objects.requireNonNull( request, "request can not be null" ); + PersistedToolchains content = Objects.requireNonNull( request.getContent(), "content can not be null" ); + OutputStream outputStream = request.getOutputStream(); + Writer writer = request.getWriter(); + if ( writer == null && outputStream == null ) + { + throw new IllegalArgumentException( "writer or outputStream must be non null" ); + } + try + { + if ( writer != null ) + { + new MavenToolchainsXpp3Writer().write( writer, content ); + } + else + { + new MavenToolchainsXpp3Writer().write( outputStream, content ); + } + } + catch ( Exception e ) + { + throw new XmlWriterException( "Unable to write toolchains", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java new file mode 100644 index 000000000000..c302752f8d02 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java @@ -0,0 +1,84 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.Type; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.TypeRegistry; +import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultTypeRegistry implements TypeRegistry +{ + + private final ArtifactHandlerManager manager; + + public DefaultTypeRegistry( ArtifactHandlerManager manager ) + { + this.manager = nonNull( manager, "artifactHandlerManager" ); + } + + @Override + @Nonnull + public Type getType( String id ) + { + // Copy data as the ArtifacHandler is not immutable, but Type should be. + ArtifactHandler handler = manager.getArtifactHandler( nonNull( id , "id" ) ); + String extension = handler.getExtension(); + String classifier = handler.getClassifier(); + boolean includeDependencies = handler.isIncludesDependencies(); + boolean addedToClasspath = handler.isAddedToClasspath(); + return new Type() + { + @Override + public String getName() + { + return id; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public boolean isIncludesDependencies() + { + return includeDependencies; + } + + @Override + public boolean isAddedToClasspath() + { + return addedToClasspath; + } + }; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java new file mode 100644 index 000000000000..03762c997877 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java @@ -0,0 +1,161 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; +import java.util.regex.Pattern; + +import org.apache.maven.api.Version; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.services.VersionParser; +import org.apache.maven.api.services.VersionParserException; +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; + +import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultVersionParser implements VersionParser +{ + private static final String SNAPSHOT = "SNAPSHOT"; + private static final Pattern SNAPSHOT_TIMESTAMP = Pattern.compile( "^(.*-)?([0-9]{8}\\.[0-9]{6}-[0-9]+)$" ); + + @Override + public Version parseVersion( String version ) + { + return new DefaultVersion( new DefaultArtifactVersion( nonNull( version, "version" ) ) ); + } + + @Override + public VersionRange parseVersionRange( String range ) + { + try + { + return new DefaultVersionRange( createFromVersionSpec( nonNull( range, "version" ) ) ); + } + catch ( InvalidVersionSpecificationException e ) + { + throw new VersionParserException( "Unable to parse version range: " + range, e ); + } + } + + @Override + public boolean isSnapshot( String version ) + { + return checkSnapshot( version ); + } + + static boolean checkSnapshot( String version ) + { + return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches(); + } + + static class DefaultVersion implements Version + { + private final ArtifactVersion delegate; + + DefaultVersion( ArtifactVersion delegate ) + { + this.delegate = delegate; + } + + @Override + public int compareTo( Version o ) + { + if ( o instanceof DefaultVersion ) + { + return delegate.compareTo( ( ( DefaultVersion ) o ).delegate ); + } + else + { + return delegate.compareTo( new DefaultArtifactVersion( o.toString() ) ); + } + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + DefaultVersion that = (DefaultVersion) o; + return delegate.equals( that.delegate ); + } + + @Override + public int hashCode() + { + return Objects.hash( delegate ); + } + + @Override + public String asString() + { + return delegate.toString(); + } + + @Override + public String toString() + { + return asString(); + } + } + + static class DefaultVersionRange implements VersionRange + { + private final org.apache.maven.artifact.versioning.VersionRange delegate; + + DefaultVersionRange( org.apache.maven.artifact.versioning.VersionRange delegate ) + { + this.delegate = delegate; + } + + @Override + public boolean contains( Version version ) + { + if ( version instanceof DefaultVersion ) + { + return delegate.containsVersion( ( ( DefaultVersion ) version ).delegate ); + } + else + { + return delegate.containsVersion( new DefaultArtifactVersion( version.toString() ) ); + } + } + + @Override + public String asString() + { + return delegate.toString(); + } + + @Override + public String toString() + { + return asString(); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java b/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java new file mode 100644 index 000000000000..255625e49193 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java @@ -0,0 +1,75 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.util.Collection; + +import org.apache.maven.api.Event; +import org.apache.maven.api.Listener; +import org.apache.maven.eventspy.EventSpy; +import org.apache.maven.execution.ExecutionEvent; + +@Named +@Singleton +public class EventSpyImpl implements EventSpy +{ + + private DefaultSessionFactory sessionFactory; + + @Inject + EventSpyImpl( DefaultSessionFactory sessionFactory ) + { + this.sessionFactory = sessionFactory; + } + + @Override + public void init( Context context ) throws Exception + { + } + + @Override + public void onEvent( Object arg ) throws Exception + { + if ( arg instanceof ExecutionEvent ) + { + ExecutionEvent ee = (ExecutionEvent) arg; + AbstractSession session = ( AbstractSession ) sessionFactory.getSession( ee.getSession() ); + Collection listeners = session.getListeners(); + if ( !listeners.isEmpty() ) + { + Event event = new DefaultEvent( session, ee ); + for ( Listener listener : listeners ) + { + listener.onEvent( event ); + } + } + } + } + + @Override + public void close() throws Exception + { + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java new file mode 100644 index 000000000000..32310800f68c --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java @@ -0,0 +1,63 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.function.Function; + +public class MappedCollection extends AbstractCollection +{ + private final Collection list; + private final Function mapper; + + public MappedCollection( Collection list, Function mapper ) + { + this.list = list; + this.mapper = mapper; + } + + @Override + public Iterator iterator() + { + Iterator it = list.iterator(); + return new Iterator() + { + @Override + public boolean hasNext() + { + return it.hasNext(); + } + + @Override + public U next() + { + return mapper.apply( it.next() ); + } + }; + } + + @Override + public int size() + { + return list.size(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java new file mode 100644 index 000000000000..e68f25941c72 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java @@ -0,0 +1,48 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.List; +import java.util.function.Function; + +public class MappedList extends AbstractList +{ + private final List list; + private final Function mapper; + + public MappedList( List list, Function mapper ) + { + this.list = list; + this.mapper = mapper; + } + + @Override + public U get( int index ) + { + return mapper.apply( list.get( index ) ); + } + + @Override + public int size() + { + return list.size(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java b/maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java new file mode 100644 index 000000000000..675f397017ba --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java @@ -0,0 +1,51 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +class Utils +{ + static T nonNull( T t ) + { + if ( t == null ) + { + throw new IllegalArgumentException(); + } + return t; + } + + static T nonNull( T t, String message ) + { + if ( t == null ) + { + throw new IllegalArgumentException( message ); + } + return t; + } + + static T cast( Class clazz, Object o, String message ) + { + if ( ! clazz.isInstance( o ) ) + { + throw new IllegalArgumentException( message ); + } + return clazz.cast( o ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java new file mode 100644 index 000000000000..066df38fa423 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java @@ -0,0 +1,81 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Nonnull; +import org.eclipse.aether.graph.DependencyNode; + +class WrapperNode extends AbstractNode +{ + protected final Node delegate; + protected final List children; + + WrapperNode( Node delegate, List children ) + { + this.delegate = delegate; + this.children = children; + } + + @Override + DependencyNode getDependencyNode() + { + return Utils.cast( AbstractNode.class, delegate, + "delegate is not an instance of AbstractNode" ).getDependencyNode(); + } + + @Override + public List getChildren() + { + return children; + } + + @Override + public Dependency getDependency() + { + return delegate.getDependency(); + } + + @Override + @Nonnull + public List getRemoteRepositories() + { + return delegate.getRemoteRepositories(); + } + + @Override + @Nonnull + public Optional getRepository() + { + return delegate.getRepository(); + } + + @Override + @Nonnull + public String asString() + { + return delegate.asString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java index 036b94047069..68491936347d 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -33,7 +34,9 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.lifecycle.DefaultLifecycles; import org.apache.maven.lifecycle.Lifecycle; import org.apache.maven.lifecycle.LifecycleMappingDelegate; @@ -58,7 +61,6 @@ import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -314,46 +316,57 @@ private void finalizeMojoConfiguration( MojoExecution mojoExecution ) { MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); - Xpp3Dom executionConfiguration = mojoExecution.getConfiguration(); + org.codehaus.plexus.util.xml.Xpp3Dom config = mojoExecution.getConfiguration(); + Dom executionConfiguration = config != null ? config.getDom() : null; if ( executionConfiguration == null ) { executionConfiguration = new Xpp3Dom( "configuration" ); } - Xpp3Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor ); - - Xpp3Dom finalConfiguration = new Xpp3Dom( "configuration" ); + Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor ); + List children = new ArrayList<>(); if ( mojoDescriptor.getParameters() != null ) { for ( Parameter parameter : mojoDescriptor.getParameters() ) { - Xpp3Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() ); + Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() ); if ( parameterConfiguration == null ) { parameterConfiguration = executionConfiguration.getChild( parameter.getAlias() ); } - Xpp3Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() ); + Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() ); - parameterConfiguration = Xpp3Dom.mergeXpp3Dom( parameterConfiguration, parameterDefaults, - Boolean.TRUE ); + if ( parameterConfiguration != null ) + { + parameterConfiguration = parameterConfiguration.merge( parameterDefaults, Boolean.TRUE ); + } + else + { + parameterConfiguration = parameterDefaults; + } if ( parameterConfiguration != null ) { - parameterConfiguration = new Xpp3Dom( parameterConfiguration, parameter.getName() ); + Map attributes = new HashMap<>( parameterConfiguration.getAttributes() ); if ( StringUtils.isEmpty( parameterConfiguration.getAttribute( "implementation" ) ) && StringUtils.isNotEmpty( parameter.getImplementation() ) ) { - parameterConfiguration.setAttribute( "implementation", parameter.getImplementation() ); + attributes.put( "implementation", parameter.getImplementation() ); } - finalConfiguration.addChild( parameterConfiguration ); + parameterConfiguration = new Xpp3Dom( parameter.getName(), parameterConfiguration.getValue(), + attributes, parameterConfiguration.getChildren(), + parameterConfiguration.getInputLocation() ); + + children.add( parameterConfiguration ); } } } + Dom finalConfiguration = new Xpp3Dom( "configuration", null, null, children, null ); mojoExecution.setConfiguration( finalConfiguration ); } @@ -549,11 +562,16 @@ private void injectLifecycleOverlay( Map> lifecycleM { for ( MojoExecution forkedExecution : forkedExecutions ) { - Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration(); + org.codehaus.plexus.util.xml.Xpp3Dom config = forkedExecution.getConfiguration(); - forkedConfiguration = Xpp3Dom.mergeXpp3Dom( phaseConfiguration, forkedConfiguration ); + if ( config != null ) + { + Dom forkedConfiguration = config.getDom(); - forkedExecution.setConfiguration( forkedConfiguration ); + forkedConfiguration = phaseConfiguration.merge( forkedConfiguration ); + + forkedExecution.setConfiguration( forkedConfiguration ); + } } } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java index b0e3fa16c4ef..c52eda83a59d 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java @@ -26,6 +26,7 @@ import java.util.NoSuchElementException; import java.util.Set; +import org.apache.maven.api.xml.Dom; import org.apache.maven.lifecycle.DefaultLifecycles; import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer; import org.apache.maven.lifecycle.Lifecycle; @@ -221,13 +222,16 @@ private void parseLifecyclePhaseDefinitions( Map plugins, String execution.setLocation( "phase", location ); execution.setLocation( "goals", location ); - Xpp3Dom lifecycleConfiguration = mojo.getConfiguration(); + Dom lifecycleConfiguration = mojo.getConfiguration(); if ( lifecycleConfiguration != null ) { execution.setConfiguration( new Xpp3Dom( lifecycleConfiguration ) ); } - plugin.setDependencies( mojo.getDependencies() ); + if ( mojo.getDependencies() != null ) + { + plugin.setDependencies( mojo.getDependencies() ); + } plugin.getExecutions().add( execution ); } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java index 298562ded350..9e362d252b30 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java @@ -27,6 +27,8 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.lifecycle.MojoExecutionConfigurator; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; @@ -37,7 +39,6 @@ import org.apache.maven.shared.utils.logging.MessageBuilder; import org.apache.maven.shared.utils.logging.MessageUtils; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -72,22 +73,23 @@ public void configure( MavenProject project, MojoExecution mojoExecution, boolea PluginExecution pluginExecution = findPluginExecution( mojoExecution.getExecutionId(), plugin.getExecutions() ); - Xpp3Dom pomConfiguration = null; + Dom pomConfiguration = null; if ( pluginExecution != null ) { - pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration(); + pomConfiguration = pluginExecution.getDelegate().getConfiguration(); } else if ( allowPluginLevelConfig ) { - pomConfiguration = (Xpp3Dom) plugin.getConfiguration(); + pomConfiguration = plugin.getDelegate().getConfiguration(); } - Xpp3Dom mojoConfiguration = ( pomConfiguration != null ) ? new Xpp3Dom( pomConfiguration ) : null; + Dom mojoConfiguration = mojoExecution.getConfiguration() != null + ? mojoExecution.getConfiguration().getDom() : null; - mojoConfiguration = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration ); + Dom mergedConfiguration = Xpp3Dom.merge( mojoConfiguration, pomConfiguration ); - mojoExecution.setConfiguration( mojoConfiguration ); + mojoExecution.setConfiguration( mergedConfiguration ); checkUnknownMojoConfigurationParameters( mojoExecution ); } @@ -190,7 +192,7 @@ private Stream getParameterNames( Parameter parameter ) private Set getUnknownParameters( MojoExecution mojoExecution, Set parameters ) { return stream( mojoExecution.getConfiguration().getChildren() ) - .map( Xpp3Dom::getName ) + .map( x -> x.getName() ) .filter( name -> !parameters.contains( name ) ) .collect( Collectors.toSet() ); } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java index a64da0490e3b..b5868e7b9218 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java @@ -50,7 +50,8 @@ public DefaultProjectArtifactFactory( ArtifactFactory artifactFactory ) public Set createArtifacts( MavenProject project ) throws InvalidDependencyVersionException { - return MavenMetadataSource.createArtifacts( artifactFactory, project.getDependencies(), null, null, project ); + return MavenMetadataSource.createArtifacts( artifactFactory, + project.getDependencies(), null, null, project ); } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java index 1eb7bebea3fe..b3b26210f0e5 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java @@ -128,32 +128,8 @@ public void resolveProjectDependencies( MavenProject project, Collection } } - Set resolvedArtifacts; - ProjectArtifactsCache.Key cacheKey = projectArtifactsCache.createKey( project, scopesToCollect, - scopesToResolve, aggregating, session.getRepositorySession() ); - ProjectArtifactsCache.CacheRecord recordArtifacts; - recordArtifacts = projectArtifactsCache.get( cacheKey ); - - if ( recordArtifacts != null ) - { - resolvedArtifacts = recordArtifacts.getArtifacts(); - } - else - { - try - { - resolvedArtifacts = getDependencies( project, scopesToCollect, scopesToResolve, session, - aggregating, projectArtifacts ); - recordArtifacts = projectArtifactsCache.put( cacheKey, resolvedArtifacts ); - } - catch ( LifecycleExecutionException e ) - { - projectArtifactsCache.put( cacheKey, e ); - projectArtifactsCache.register( project, cacheKey, recordArtifacts ); - throw e; - } - } - projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + Set resolvedArtifacts = resolveProjectArtifacts( project, scopesToCollect, scopesToResolve, + session, aggregating, projectArtifacts ); Map reactorProjects = new HashMap<>( session.getProjects().size() ); for ( MavenProject reactorProject : session.getProjects() ) @@ -201,6 +177,40 @@ public void resolveProjectDependencies( MavenProject project, Collection } } + public Set resolveProjectArtifacts( MavenProject project, Collection scopesToCollect, + Collection scopesToResolve, MavenSession session, + boolean aggregating, Set projectArtifacts ) + throws LifecycleExecutionException + { + Set resolvedArtifacts; + ProjectArtifactsCache.Key cacheKey = projectArtifactsCache.createKey( project, scopesToCollect, + scopesToResolve, aggregating, session.getRepositorySession() ); + ProjectArtifactsCache.CacheRecord recordArtifacts; + recordArtifacts = projectArtifactsCache.get( cacheKey ); + + if ( recordArtifacts != null ) + { + resolvedArtifacts = recordArtifacts.getArtifacts(); + } + else + { + try + { + resolvedArtifacts = getDependencies( project, scopesToCollect, scopesToResolve, session, + aggregating, projectArtifacts ); + recordArtifacts = projectArtifactsCache.put( cacheKey, resolvedArtifacts ); + } + catch ( LifecycleExecutionException e ) + { + projectArtifactsCache.put( cacheKey, e ); + projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + throw e; + } + } + projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + return resolvedArtifacts; + } + private Set getDependencies( MavenProject project, Collection scopesToCollect, Collection scopesToResolve, MavenSession session, boolean aggregating, Set projectArtifacts ) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java index 778aa33b0aca..04a247ae03fc 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java @@ -21,13 +21,17 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.StringTokenizer; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.BuildPluginManager; import org.apache.maven.plugin.InvalidPluginDescriptorException; @@ -47,7 +51,6 @@ import org.apache.maven.plugin.version.PluginVersionResolver; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.configuration.PlexusConfiguration; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -101,12 +104,10 @@ private Plugin findPlugin( String groupId, String artifactId, Collection public static Xpp3Dom convert( MojoDescriptor mojoDescriptor ) { - Xpp3Dom dom = new Xpp3Dom( "configuration" ); - PlexusConfiguration c = mojoDescriptor.getMojoConfiguration(); + List children = new ArrayList<>(); PlexusConfiguration[] ces = c.getChildren(); - if ( ces != null ) { for ( PlexusConfiguration ce : ces ) @@ -115,17 +116,15 @@ public static Xpp3Dom convert( MojoDescriptor mojoDescriptor ) String defaultValue = ce.getAttribute( "default-value", null ); if ( value != null || defaultValue != null ) { - Xpp3Dom e = new Xpp3Dom( ce.getName() ); - e.setValue( value ); - if ( defaultValue != null ) - { - e.setAttribute( "default-value", defaultValue ); - } - dom.addChild( e ); + Xpp3Dom e = new Xpp3Dom( ce.getName(), value, + defaultValue != null ? Collections.singletonMap( "default-value", defaultValue ) : null, + null, null ); + children.add( e ); } } } + Xpp3Dom dom = new Xpp3Dom( "configuration", null, null, children, null ); return dom; } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java index 5415413af83a..47e9a1edcd3f 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java @@ -179,9 +179,9 @@ public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject p List unversionedPlugins = executionPlan.getMojoExecutions().stream() .map( MojoExecution::getPlugin ) - .filter( p -> p.getLocation( "version" ) != null ) // versionless cli goal (?) - .filter( p -> p.getLocation( "version" ).getSource() != null ) // versionless in pom (?) - .filter( p -> defaulModelId.equals( p.getLocation( "version" ).getSource().getModelId() ) ) + .filter( p -> p.getLocation( "version" ) != null + && p.getLocation( "version" ).getSource() != null + && defaulModelId.equals( p.getLocation( "version" ).getSource().getModelId() ) ) .distinct() .map( Plugin::getArtifactId ) // managed by us, groupId is always o.a.m.plugins .collect( Collectors.toList() ); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java b/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java index 1e274c49627b..f928c5095ea8 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java @@ -21,8 +21,8 @@ import java.util.List; +import org.apache.maven.api.xml.Dom; import org.apache.maven.model.Dependency; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Mojo (plugin goal) binding to a lifecycle phase. @@ -33,7 +33,7 @@ public class LifecycleMojo { private String goal; - private Xpp3Dom configuration; + private Dom configuration; private List dependencies; public String getGoal() @@ -41,7 +41,7 @@ public String getGoal() return goal; } - public Xpp3Dom getConfiguration() + public Dom getConfiguration() { return configuration; } @@ -56,7 +56,7 @@ public void setGoal( String goal ) this.goal = goal; } - public void setConfiguration( Xpp3Dom configuration ) + public void setConfiguration( Dom configuration ) { this.configuration = configuration; } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java index e167cac59b9b..27ea758c7d3a 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import javax.inject.Provider; @@ -48,7 +49,7 @@ protected AbstractLifecycleProvider( String id, String[] phases, String[] plugin throw new IllegalArgumentException( "Plugin bindings must have more than 0, even count of elements" ); } - defaultBindings = new HashMap<>( len / 2 ); + defaultBindings = new LinkedHashMap<>( len / 2 ); for ( int i = 0; i < len; i += 2 ) { diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java index db42df1c03c2..4ffbdbbb439f 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java @@ -40,8 +40,10 @@ public final class CleanLifecycleProvider "post-clean" }; + private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.1.0"; + private static final String[] BINDINGS = { - "clean", "org.apache.maven.plugins:maven-clean-plugin:3.1.0:clean" + "clean", "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION + ":clean" }; // END SNIPPET: clean diff --git a/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java b/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java index ec0800f013cf..688b60908960 100644 --- a/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java +++ b/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java @@ -25,18 +25,19 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; @@ -65,11 +66,13 @@ public DefaultLifecycleBindingsInjector( LifeCyclePluginAnalyzer lifecycle ) this.lifecycle = lifecycle; } - public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectLifecycleBindings( org.apache.maven.model.Model model, ModelBuildingRequest request, + ModelProblemCollector problems ) { String packaging = model.getPackaging(); - Collection defaultPlugins = lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging ); + Collection defaultPlugins = + lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging ); if ( defaultPlugins == null ) { @@ -79,11 +82,13 @@ public void injectLifecycleBindings( Model model, ModelBuildingRequest request, } else if ( !defaultPlugins.isEmpty() ) { - Model lifecycleModel = new Model(); - lifecycleModel.setBuild( new Build() ); - lifecycleModel.getBuild().getPlugins().addAll( defaultPlugins ); - - merger.merge( model, lifecycleModel ); + List plugins = defaultPlugins.stream() + .map( org.apache.maven.model.Plugin::getDelegate ) + .collect( Collectors.toList() ); + Model lifecycleModel = Model.newBuilder() + .build( Build.newBuilder().plugins( plugins ).build() ) + .build(); + model.update( merger.merge( model.getDelegate(), lifecycleModel ) ); } } @@ -96,22 +101,27 @@ protected static class LifecycleBindingsMerger private static final String PLUGIN_MANAGEMENT = "plugin-management"; - public void merge( Model target, Model source ) + public Model merge( Model target, Model source ) { - if ( target.getBuild() == null ) + Build targetBuild = target.getBuild(); + if ( targetBuild == null ) { - target.setBuild( new Build() ); + targetBuild = Build.newInstance(); } Map context = Collections.singletonMap( PLUGIN_MANAGEMENT, target.getBuild().getPluginManagement() ); - mergePluginContainer_Plugins( target.getBuild(), source.getBuild(), false, context ); + Build.Builder builder = Build.newBuilder( target.getBuild() ); + mergePluginContainer_Plugins( builder, targetBuild, source.getBuild(), false, context ); + + return target.withBuild( builder.build() ); } @SuppressWarnings( { "checkstyle:methodname" } ) @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, boolean sourceDominant, Map context ) { List src = source.getPlugins(); @@ -135,13 +145,13 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin existing = merged.get( key ); if ( existing != null ) { - mergePlugin( existing, element, sourceDominant, context ); + element = mergePlugin( existing, element, sourceDominant, context ); } else { - merged.put( key, element ); added.put( key, element ); } + merged.put( key, element ); } if ( !added.isEmpty() ) @@ -155,8 +165,8 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin addedPlugin = added.get( key ); if ( addedPlugin != null ) { - Plugin plugin = managedPlugin.clone(); - mergePlugin( plugin, addedPlugin, sourceDominant, Collections.emptyMap() ); + Plugin plugin = mergePlugin( managedPlugin, addedPlugin, + sourceDominant, Collections.emptyMap() ); merged.put( key, plugin ); } } @@ -165,18 +175,22 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta List result = new ArrayList<>( merged.values() ); - target.setPlugins( result ); + builder.plugins( result ); } } @Override - protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) + protected void mergePluginExecution_Priority( PluginExecution.Builder builder, PluginExecution target, + PluginExecution source, boolean sourceDominant, + Map context ) { - super.mergePluginExecution( target, source, sourceDominant, context ); - - target.setPriority( Math.min( target.getPriority(), source.getPriority() ) ); + if ( target.getPriority() > source.getPriority() ) + { + builder.priority( source.getPriority() ); + builder.location( "priority", source.getLocation( "priority" ) ); + } } + //mergePluginExecution_Priority( builder, target, source, sourceDominant, context ); } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java b/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java index f77461fe377a..d7f6e8ad7f7f 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Plugin; import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException; /** diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index 272371ade084..a5c284458a5b 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -27,17 +27,24 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.Project; +import org.apache.maven.api.plugin.MojoException; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.internal.impl.DefaultLog; +import org.apache.maven.internal.impl.DefaultMojoExecution; +import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.repository.RemoteRepository; +import org.slf4j.LoggerFactory; // TODO the antrun plugin has its own configurator, the only plugin that does. might need to think about how that works // TODO remove the coreArtifactFilterManager @@ -120,8 +127,21 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) { scope.seed( MavenProject.class, project ); scope.seed( MojoExecution.class, mojoExecution ); + scope.seed( org.apache.maven.api.plugin.Log.class, new DefaultLog( + LoggerFactory.getLogger( mojoExecution.getMojoDescriptor().getFullGoalName() ) ) ); + scope.seed( Project.class, ( ( DefaultSession) session.getSession() ).getProject( project ) ); + scope.seed( org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution( mojoExecution ) ); - mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); + if ( mojoDescriptor.isV4Api() ) + { + org.apache.maven.api.plugin.Mojo mojoV4 = mavenPluginManager.getConfiguredMojo( + org.apache.maven.api.plugin.Mojo.class, session, mojoExecution ); + mojo = new MojoWrapper( mojoV4 ); + } + else + { + mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); + } legacySupport.setSession( session ); @@ -131,11 +151,8 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) try { MojoExecutionEvent mojoExecutionEvent = new MojoExecutionEvent( session, project, mojoExecution, mojo ); - mojoExecutionListener.beforeMojoExecution( mojoExecutionEvent ); - mojo.execute(); - mojoExecutionListener.afterMojoExecutionSuccess( mojoExecutionEvent ); } catch ( ClassCastException e ) @@ -150,69 +167,56 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) } catch ( PluginContainerException e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); throw new PluginExecutionException( mojoExecution, project, e ); } catch ( NoClassDefFoundError e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); ps.println( "A required class was missing while executing " + mojoDescriptor.getId() + ": " + e.getMessage() ); pluginRealm.display( ps ); - Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); - throw new PluginExecutionException( mojoExecution, project, wrapper ); } catch ( LinkageError e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); ps.println( "An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": " + e.getClass().getName() + ": " + e.getMessage() ); pluginRealm.display( ps ); - Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); - throw new PluginExecutionException( mojoExecution, project, wrapper ); } catch ( ClassCastException e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); ps.println( "A type incompatibility occurred while executing " + mojoDescriptor.getId() + ": " + e.getMessage() ); pluginRealm.display( ps ); - throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); } catch ( RuntimeException e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); throw e; } finally { mavenPluginManager.releaseMojo( mojo, mojoExecution ); - scope.exit(); - Thread.currentThread().setContextClassLoader( oldClassLoader ); - legacySupport.setSession( oldSession ); } } @@ -244,4 +248,37 @@ public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, List${ and } is evaluated. + * Recognized values are: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Expression matrix
expression evaluation result
session the actual {@link Session}
session.* (since Maven 3)
localRepository {@link Session#getLocalRepository()}
reactorProjects {@link MavenSession#getProjects()}
project {@link Session#getCurrentProject()}
project.*
pom.* (since Maven 3)same as project.*
executedProject {@link MavenProject#getExecutionProject()}
settings {@link Session#getSettings()}
settings.*
basedir {@link Session#getExecutionRootDirectory()} or + * System.getProperty( "user.dir" ) if null
mojoExecution the actual {@link MojoExecution}
mojo (since Maven 3)same as mojoExecution
mojo.* (since Maven 3)
plugin (since Maven 3){@link MojoExecution#getMojoDescriptor()}.{@link MojoDescriptor#getPluginDescriptor() + * getPluginDescriptor()}
plugin.*
* system properties
* project properties
+ * Notice: reports was supported in Maven 2.x but was removed in Maven 3 + * + * @author Jason van Zyl + * @see Session + * @see MojoExecution + */ +public class PluginParameterExpressionEvaluatorV4 + implements TypeAwareExpressionEvaluator +{ + private Session session; + + private MojoExecution mojoExecution; + + private Project project; + + private Path basedir; + + private Properties properties; + + public PluginParameterExpressionEvaluatorV4( Session session, Project project ) + { + this( session, project, null ); + } + + public PluginParameterExpressionEvaluatorV4( Session session, Project project, MojoExecution mojoExecution ) + { + this.session = session; + this.mojoExecution = mojoExecution; + this.properties = new Properties(); + this.project = project; + + // + // Maven4: We may want to evaluate how this is used but we add these separate as the + // getExecutionProperties is deprecated in MavenSession. + // + this.properties.putAll( session.getUserProperties() ); + this.properties.putAll( session.getSystemProperties() ); + + Path basedir = null; + + if ( project != null ) + { + Optional projectFile = project.getBasedir(); + + // this should always be the case for non-super POM instances... + if ( projectFile.isPresent() ) + { + basedir = projectFile.get().toAbsolutePath(); + } + } + + if ( basedir == null ) + { + basedir = session.getExecutionRootDirectory(); + } + + if ( basedir == null ) + { + basedir = Paths.get( System.getProperty( "user.dir" ) ); + } + + this.basedir = basedir; + } + + @Override + public Object evaluate( String expr ) + throws ExpressionEvaluationException + { + return evaluate( expr, null ); + } + + @Override + @SuppressWarnings( "checkstyle:methodlength" ) + public Object evaluate( String expr, Class type ) + throws ExpressionEvaluationException + { + Object value = null; + + if ( expr == null ) + { + return null; + } + + String expression = stripTokens( expr ); + if ( expression.equals( expr ) ) + { + int index = expr.indexOf( "${" ); + if ( index >= 0 ) + { + int lastIndex = expr.indexOf( '}', index ); + if ( lastIndex >= 0 ) + { + String retVal = expr.substring( 0, index ); + + if ( ( index > 0 ) && ( expr.charAt( index - 1 ) == '$' ) ) + { + retVal += expr.substring( index + 1, lastIndex + 1 ); + } + else + { + Object subResult = evaluate( expr.substring( index, lastIndex + 1 ) ); + + if ( subResult != null ) + { + retVal += subResult; + } + else + { + retVal += "$" + expr.substring( index + 1, lastIndex + 1 ); + } + } + + retVal += evaluate( expr.substring( lastIndex + 1 ) ); + return retVal; + } + } + + // Was not an expression + if ( expression.contains( "$$" ) ) + { + return expression.replaceAll( "\\$\\$", "\\$" ); + } + else + { + return expression; + } + } + + if ( "localRepository".equals( expression ) ) + { + // TODO: v4 + value = session.getLocalRepository(); + } + else if ( "session".equals( expression ) ) + { + value = session; + } + else if ( expression.startsWith( "session" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, session ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), session ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( "reactorProjects".equals( expression ) ) + { + value = session.getProjects(); + } + else if ( "project".equals( expression ) ) + { + value = project; + } + else if ( "executedProject".equals( expression ) ) + { + value = ( (DefaultSession) session ).getProject( + ( (DefaultSession) session ).getMavenSession().getCurrentProject().getExecutionProject() ); + } + else if ( expression.startsWith( "project" ) || expression.startsWith( "pom" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 0, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, project ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), project ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( expression.equals( "repositorySystemSession" ) ) + { + // TODO: v4 + } + else if ( expression.equals( "mojo" ) || expression.equals( "mojoExecution" ) ) + { + value = new DefaultMojoExecution( mojoExecution ); + } + else if ( expression.startsWith( "mojo" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, mojoExecution ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), mojoExecution ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( expression.equals( "plugin" ) ) + { + // TODO: v4 + value = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + } + else if ( expression.startsWith( "plugin" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, pluginDescriptor ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), pluginDescriptor ); + } + } + catch ( Exception e ) + { + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( "settings".equals( expression ) ) + { + value = session.getSettings(); + } + else if ( expression.startsWith( "settings" ) ) + { + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, session.getSettings() ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), session.getSettings() ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( "basedir".equals( expression ) ) + { + value = basedir.toString(); + } + else if ( expression.startsWith( "basedir" ) ) + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + value = basedir.toString() + expression.substring( pathSeparator ); + } + } + + /* + * MNG-4312: We neither have reserved all of the above magic expressions nor is their set fixed/well-known (it + * gets occasionally extended by newer Maven versions). This imposes the risk for existing plugins to + * unintentionally use such a magic expression for an ordinary system property. So here we check whether we + * ended up with a magic value that is not compatible with the type of the configured mojo parameter (a string + * could still be converted by the configurator so we leave those alone). If so, back off to evaluating the + * expression from properties only. + */ + if ( value != null && type != null && !( value instanceof String ) && !isTypeCompatible( type, value ) ) + { + value = null; + } + + if ( value == null ) + { + // The CLI should win for defining properties + + if ( properties != null ) + { + // We will attempt to get nab a system property as a way to specify a + // parameter to a plugins. My particular case here is allowing the surefire + // plugin to run a single test so I want to specify that class on the cli + // as a parameter. + + value = properties.getProperty( expression ); + } + + if ( ( value == null ) && ( ( project != null ) && ( project.getModel().getProperties() != null ) ) ) + { + value = project.getModel().getProperties().getProperty( expression ); + } + + } + + if ( value instanceof String ) + { + // TODO without #, this could just be an evaluate call... + + String val = (String) value; + + int exprStartDelimiter = val.indexOf( "${" ); + + if ( exprStartDelimiter >= 0 ) + { + if ( exprStartDelimiter > 0 ) + { + value = val.substring( 0, exprStartDelimiter ) + evaluate( val.substring( exprStartDelimiter ) ); + } + else + { + value = evaluate( val.substring( exprStartDelimiter ) ); + } + } + } + + return value; + } + + private static boolean isTypeCompatible( Class type, Object value ) + { + if ( type.isInstance( value ) ) + { + return true; + } + // likely Boolean -> boolean, Short -> int etc. conversions, it's not the problem case we try to avoid + return ( ( type.isPrimitive() || type.getName().startsWith( "java.lang." ) ) + && value.getClass().getName().startsWith( "java.lang." ) ); + } + + private String stripTokens( String expr ) + { + if ( expr.startsWith( "${" ) && ( expr.indexOf( '}' ) == expr.length() - 1 ) ) + { + expr = expr.substring( 2, expr.length() - 1 ); + } + return expr; + } + + @Override + public File alignToBaseDirectory( File file ) + { + // TODO Copied from the DefaultInterpolator. We likely want to resurrect the PathTranslator or at least a + // similar component for re-usage + if ( file != null ) + { + if ( file.isAbsolute() ) + { + // path was already absolute, just normalize file separator and we're done + } + else if ( file.getPath().startsWith( File.separator ) ) + { + // drive-relative Windows path, don't align with project directory but with drive root + file = file.getAbsoluteFile(); + } + else + { + // an ordinary relative path, align with project directory + file = basedir.resolve( file.getPath() ).normalize().toAbsolutePath().toFile(); + } + } + return file; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 71c355a25c94..de249c727aef 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -20,10 +20,12 @@ */ import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.xml.Dom; import org.apache.maven.artifact.Artifact; import org.apache.maven.classrealm.ClassRealmManager; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule; +import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.ContextEnabled; import org.apache.maven.plugin.DebugConfigurationListener; @@ -42,6 +44,7 @@ import org.apache.maven.plugin.PluginManagerException; import org.apache.maven.plugin.PluginParameterException; import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.PluginParameterExpressionEvaluatorV4; import org.apache.maven.plugin.PluginRealmCache; import org.apache.maven.plugin.PluginResolutionException; import org.apache.maven.plugin.descriptor.MojoDescriptor; @@ -57,6 +60,7 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.session.scope.internal.SessionScopeModule; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.codehaus.plexus.DefaultPlexusContainer; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.classworlds.realm.ClassRealm; @@ -69,12 +73,11 @@ import org.codehaus.plexus.component.repository.ComponentDescriptor; import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.configuration.DefaultPlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfigurationException; -import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.graph.DependencyFilter; import org.eclipse.aether.graph.DependencyNode; @@ -149,6 +152,7 @@ public class DefaultMavenPluginManager private final PluginDescriptorBuilder builder = new PluginDescriptorBuilder(); @Inject + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultMavenPluginManager( PlexusContainer container, ClassRealmManager classRealmManager, @@ -591,20 +595,32 @@ else if ( cause instanceof LinkageError ) ( (Mojo) mojo ).setLog( new MojoLogWrapper( mojoLogger ) ); } - Xpp3Dom dom = mojoExecution.getConfiguration(); + Dom dom = mojoExecution.getConfiguration() != null + ? mojoExecution.getConfiguration().getDom() : null; PlexusConfiguration pomConfiguration; if ( dom == null ) { - pomConfiguration = new XmlPlexusConfiguration( "configuration" ); + pomConfiguration = new DefaultPlexusConfiguration( "configuration" ); } else { - pomConfiguration = new XmlPlexusConfiguration( dom ); + pomConfiguration = XmlPlexusConfiguration.toPlexusConfiguration( dom ); } - ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution ); + ExpressionEvaluator expressionEvaluator; + if ( mojoDescriptor.isV4Api() ) + { + expressionEvaluator = new PluginParameterExpressionEvaluatorV4( + session.getSession(), + ( ( DefaultSession ) session.getSession() ).getProject( session.getCurrentProject() ), + mojoExecution ); + } + else + { + expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution ); + } for ( MavenPluginConfigurationValidator validator: configurationValidators ) { @@ -634,7 +650,7 @@ private void populateMojoExecutionFields( Object mojo, String executionId, MojoD if ( StringUtils.isEmpty( configuratorId ) ) { - configuratorId = "basic"; + configuratorId = mojoDescriptor.isV4Api() ? "enhanced" : "basic"; } try @@ -838,6 +854,8 @@ public ExtensionRealmCache.CacheRecord setupExtensionsRealm( MavenProject projec } } + // TODO: store plugin version + // resolve plugin artifacts List artifacts; PluginArtifactsCache.Key cacheKey = pluginArtifactsCache.createKey( plugin, null, repositories, session ); diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index f364d4cb86f6..7fe5a23b1314 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -104,6 +104,7 @@ public class DefaultProjectBuilder private final ProjectDependenciesResolver dependencyResolver; private final ModelCacheFactory modelCacheFactory; + @SuppressWarnings( "checkstyle:ParameterNumber" ) @Inject public DefaultProjectBuilder( ModelBuilder modelBuilder, @@ -260,9 +261,9 @@ private DependencyResolutionResult resolveDependencies( MavenProject project, Re return resolutionResult; } - private List getProfileIds( List profiles ) + private List getProfileIds( List profiles ) { - return profiles.stream().map( Profile::getId ).collect( Collectors.toList() ); + return profiles.stream().map( org.apache.maven.model.Profile::getId ).collect( Collectors.toList() ); } private ModelBuildingRequest getModelBuildingRequest( InternalConfig config ) @@ -484,7 +485,7 @@ private boolean build( List results, List noErrors = false; } - Model model = result.getFileModel().clone(); + Model model = result.getFileModel(); poolBuilder.put( model.getPomFile().toPath(), model ); @@ -515,8 +516,8 @@ private boolean build( List results, List { ModelProblem problem = new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile - + " does not exist", ModelProblem.Severity.ERROR, ModelProblem.Version.BASE, model, -1, - -1, null ); + + " does not exist", ModelProblem.Severity.ERROR, ModelProblem.Version.BASE, + model, -1, -1, null ); result.getProblems().add( problem ); noErrors = false; @@ -553,7 +554,7 @@ private boolean build( List results, List ModelProblem problem = new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer, ModelProblem.Severity.ERROR, - ModelProblem.Version.BASE, model, -1, -1, null ); + ModelProblem.Version.BASE, model, -1, -1, null ); result.getProblems().add( problem ); noErrors = false; @@ -675,9 +676,7 @@ private void initProject( MavenProject project, Map projects boolean buildParentIfNotExisting, ModelBuildingResult result, Map profilesXmls, ProjectBuildingRequest projectBuildingRequest ) { - Model model = result.getEffectiveModel(); - - project.setModel( model ); + project.setModel( result.getEffectiveModel() ); project.setOriginalModel( result.getFileModel() ); initParent( project, projects, buildParentIfNotExisting, result, projectBuildingRequest ); @@ -1000,11 +999,11 @@ private static String inheritedVersion( final ModelBuildingResult result, final if ( !modelId.isEmpty() ) { - final Model model = result.getRawModel( modelId ); - version = model.getVersion() != null - ? model.getVersion() - : inheritedVersion( result, modelIndex + 1 ); - + version = result.getRawModel( modelId ).getVersion(); + if ( version == null ) + { + version = inheritedVersion( result, modelIndex + 1 ); + } } return version; diff --git a/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java b/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java index 6880e7a5889d..1eb3e33e7977 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java @@ -19,9 +19,9 @@ * under the License. */ +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.ReaderFactory; -import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import java.io.BufferedInputStream; @@ -101,7 +101,7 @@ public ExtensionDescriptor build( InputStream is ) { ExtensionDescriptor extensionDescriptor = new ExtensionDescriptor(); - Xpp3Dom dom; + Dom dom; try { dom = Xpp3DomBuilder.build( ReaderFactory.newXmlReader( is ) ); @@ -123,7 +123,7 @@ public ExtensionDescriptor build( InputStream is ) return extensionDescriptor; } - private List parseStrings( Xpp3Dom dom ) + private List parseStrings( Dom dom ) { List strings = null; @@ -131,7 +131,7 @@ private List parseStrings( Xpp3Dom dom ) { strings = new ArrayList<>(); - for ( Xpp3Dom child : dom.getChildren() ) + for ( Dom child : dom.getChildren() ) { String string = child.getValue(); if ( string != null ) diff --git a/maven-core/src/main/java/org/apache/maven/project/MavenProject.java b/maven-core/src/main/java/org/apache/maven/project/MavenProject.java index 4501d799fdc2..99b175cae592 100644 --- a/maven-core/src/main/java/org/apache/maven/project/MavenProject.java +++ b/maven-core/src/main/java/org/apache/maven/project/MavenProject.java @@ -193,6 +193,11 @@ public MavenProject() setModel( model ); } + public MavenProject( org.apache.maven.api.model.Model model ) + { + this( new Model( model ) ); + } + public MavenProject( Model model ) { setModel( model ); @@ -969,11 +974,14 @@ public Xpp3Dom getGoalConfiguration( String pluginGroupId, String pluginArtifact if ( executionId != null ) { - PluginExecution execution = plugin.getExecutionsAsMap().get( executionId ); - if ( execution != null ) + for ( PluginExecution execution : plugin.getExecutions() ) { - // NOTE: The PluginConfigurationExpander already merged the plugin-level config in - dom = (Xpp3Dom) execution.getConfiguration(); + if ( executionId.equals( execution.getId() ) ) + { + // NOTE: The PluginConfigurationExpander already merged the plugin-level config in + dom = (Xpp3Dom) execution.getConfiguration(); + break; + } } } break; @@ -1549,7 +1557,8 @@ public Set createArtifacts( ArtifactFactory artifactFactory, String in ArtifactFilter filter ) throws InvalidDependencyVersionException { - return MavenMetadataSource.createArtifacts( artifactFactory, getDependencies(), inheritedScope, filter, this ); + return MavenMetadataSource.createArtifacts( artifactFactory, getModel().getDependencies(), + inheritedScope, filter, this ); } @Deprecated diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java index 9caa3e6c3f3f..5f9529383cae 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java @@ -25,11 +25,12 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; -import org.apache.maven.model.Dependency; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; import org.apache.maven.model.building.ArtifactModelSource; import org.apache.maven.model.building.FileModelSource; import org.apache.maven.model.building.ModelSource; @@ -138,7 +139,8 @@ public void addRepository( final Repository repository, boolean replace ) } List newRepositories = - Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( repository ) ); + Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( + new org.apache.maven.model.Repository( repository ) ) ); if ( ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals( repositoryMerging ) ) { @@ -192,7 +194,7 @@ public ModelSource resolveModel( String groupId, String artifactId, String versi } @Override - public ModelSource resolveModel( final Parent parent ) + public ModelSource resolveModel( final Parent parent, AtomicReference modified ) throws UnresolvableModelException { try @@ -226,9 +228,13 @@ public ModelSource resolveModel( final Parent parent ) } - parent.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !parent.getVersion().equals( newVersion ) ) + { + modified.set( parent.withVersion( newVersion ) ); + } - return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); + return resolveModel( parent.getGroupId(), parent.getArtifactId(), newVersion ); } catch ( final VersionRangeResolutionException e ) { @@ -239,7 +245,7 @@ public ModelSource resolveModel( final Parent parent ) } @Override - public ModelSource resolveModel( final Dependency dependency ) + public ModelSource resolveModel( final Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { try @@ -273,12 +279,16 @@ public ModelSource resolveModel( final Dependency dependency ) } - dependency.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !dependency.getVersion().equals( newVersion ) ) + { + modified.set( dependency.withVersion( newVersion ) ); + } if ( modelPool != null ) { Model model = - modelPool.get( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + modelPool.get( dependency.getGroupId(), dependency.getArtifactId(), newVersion ); if ( model != null ) { @@ -286,7 +296,7 @@ public ModelSource resolveModel( final Dependency dependency ) } } - return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), newVersion ); } catch ( VersionRangeResolutionException e ) { @@ -295,4 +305,41 @@ public ModelSource resolveModel( final Dependency dependency ) } } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException + { + AtomicReference resolvedParent = new AtomicReference<>(); + ModelSource result = resolveModel( parent.getDelegate(), resolvedParent ); + if ( resolvedParent.get() != null ) + { + parent.setVersion( resolvedParent.get().getVersion() ); + } + return result; + } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException + { + AtomicReference resolvedDependency = new AtomicReference<>(); + ModelSource result = resolveModel( dependency.getDelegate(), resolvedDependency ); + if ( resolvedDependency.get() != null ) + { + dependency.setVersion( resolvedDependency.get().getVersion() ); + } + return result; + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException + { + addRepository( repository.getDelegate() ); + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository, boolean replace ) + throws InvalidRepositoryException + { + addRepository( repository.getDelegate(), replace ); + } } diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java b/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java index 1051638b3c97..eaa4ce7629da 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java @@ -26,11 +26,12 @@ import java.util.Map; import java.util.stream.Collectors; +import org.apache.maven.api.model.Build; import org.apache.maven.artifact.ArtifactUtils; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Extension; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Extension; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Plugin; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.dag.CycleDetectedException; import org.codehaus.plexus.util.dag.DAG; @@ -107,13 +108,13 @@ public ProjectSorter( Collection projects ) MavenProject project = projectMap.get( projectId ); - for ( Dependency dependency : project.getDependencies() ) + for ( Dependency dependency : project.getModel().getDelegate().getDependencies() ) { addEdge( projectMap, vertexMap, project, projectVertex, dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), false, false ); } - Parent parent = project.getModel().getParent(); + Parent parent = project.getModel().getDelegate().getParent(); if ( parent != null ) { @@ -123,22 +124,26 @@ public ProjectSorter( Collection projects ) parent.getVersion(), true, false ); } - for ( Plugin plugin : project.getBuildPlugins() ) + Build build = project.getModel().getDelegate().getBuild(); + if ( build != null ) { - addEdge( projectMap, vertexMap, project, projectVertex, plugin.getGroupId(), - plugin.getArtifactId(), plugin.getVersion(), false, true ); - - for ( Dependency dependency : plugin.getDependencies() ) + for ( Plugin plugin : build.getPlugins() ) { - addEdge( projectMap, vertexMap, project, projectVertex, dependency.getGroupId(), - dependency.getArtifactId(), dependency.getVersion(), false, true ); + addEdge( projectMap, vertexMap, project, projectVertex, plugin.getGroupId(), + plugin.getArtifactId(), plugin.getVersion(), false, true ); + + for ( Dependency dependency : plugin.getDependencies() ) + { + addEdge( projectMap, vertexMap, project, projectVertex, dependency.getGroupId(), + dependency.getArtifactId(), dependency.getVersion(), false, true ); + } } - } - for ( Extension extension : project.getBuildExtensions() ) - { - addEdge( projectMap, vertexMap, project, projectVertex, extension.getGroupId(), - extension.getArtifactId(), extension.getVersion(), false, true ); + for ( Extension extension : build.getExtensions() ) + { + addEdge( projectMap, vertexMap, project, projectVertex, extension.getGroupId(), + extension.getArtifactId(), extension.getVersion(), false, true ); + } } } diff --git a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java index b55110a8400d..7f7b658c2ac0 100644 --- a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java +++ b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java @@ -231,9 +231,9 @@ else if ( artifact instanceof ArtifactWithDependencies ) } else { - dependencies = rel.project.getDependencies(); + dependencies = rel.project.getModel().getDependencies(); - DependencyManagement depMgmt = rel.project.getDependencyManagement(); + DependencyManagement depMgmt = rel.project.getModel().getDependencyManagement(); managedDependencies = ( depMgmt != null ) ? depMgmt.getDependencies() : null; pomRepositories = rel.project.getRemoteArtifactRepositories(); @@ -618,7 +618,7 @@ else if ( isNonTransferablePom( e ) ) { Relocation relocation = null; - DistributionManagement distMgmt = project.getDistributionManagement(); + DistributionManagement distMgmt = project.getModel().getDistributionManagement(); if ( distMgmt != null ) { relocation = distMgmt.getRelocation(); diff --git a/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java b/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java index a3a8dd6f9d4a..8ef44448221d 100644 --- a/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java @@ -53,12 +53,12 @@ public MavenProject getProject() public List getDependencies() { - return project.getDependencies(); + return project.getModel().getDependencies(); } public List getManagedDependencies() { - DependencyManagement depMngt = project.getDependencyManagement(); + DependencyManagement depMngt = project.getModel().getDependencyManagement(); return ( depMngt != null ) ? Collections.unmodifiableList( depMngt.getDependencies() ) : Collections.emptyList(); diff --git a/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java b/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java index b00c58841ee3..ba93ad919795 100644 --- a/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java +++ b/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java @@ -23,6 +23,7 @@ import javax.inject.Named; import org.apache.maven.SessionScoped; +import org.apache.maven.api.Session; import org.apache.maven.execution.MavenSession; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @@ -62,5 +63,6 @@ protected void configure() bind( SessionScope.class ).toInstance( scope ); bind( MavenSession.class ).toProvider( SessionScope.seededKeyProvider() ).in( scope ); + bind( Session.class ).toProvider( SessionScope.seededKeyProvider() ).in( scope ); } } diff --git a/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java b/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java index 2f2c4075e70c..151b2e5fd6bf 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java @@ -26,6 +26,7 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.settings.Settings; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.properties.internal.SystemProperties; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; diff --git a/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java b/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java index c79a843d91a6..45bcbc368261 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; +import org.apache.maven.api.settings.Settings; import org.apache.maven.execution.MavenExecutionRequest; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; diff --git a/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java b/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java index 8da696e8accc..124dcf957666 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java +++ b/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java @@ -19,10 +19,19 @@ * under the License. */ -import org.apache.maven.model.ActivationFile; -import org.apache.maven.settings.merge.MavenSettingsMerger; - +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; + +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.settings.Activation; +import org.apache.maven.api.settings.ActivationOS; +import org.apache.maven.api.settings.ActivationProperty; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.RepositoryPolicy; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.merge.MavenSettingsMerger; /** * Several convenience methods to handle settings @@ -42,9 +51,9 @@ private SettingsUtils() * @param recessive * @param recessiveSourceLevel */ - public static void merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) + public static Settings merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) { - new MavenSettingsMerger().merge( dominant, recessive, recessiveSourceLevel ); + return new MavenSettingsMerger().merge( dominant, recessive, recessiveSourceLevel ); } /** @@ -53,80 +62,86 @@ public static void merge( Settings dominant, Settings recessive, String recessiv */ public static Profile convertToSettingsProfile( org.apache.maven.model.Profile modelProfile ) { - Profile profile = new Profile(); + Profile.Builder profile = Profile.newBuilder(); - profile.setId( modelProfile.getId() ); + profile.id( modelProfile.getId() ); org.apache.maven.model.Activation modelActivation = modelProfile.getActivation(); if ( modelActivation != null ) { - Activation activation = new Activation(); + Activation.Builder activation = Activation.newBuilder(); - activation.setActiveByDefault( modelActivation.isActiveByDefault() ); + activation.activeByDefault( modelActivation.isActiveByDefault() ); - activation.setJdk( modelActivation.getJdk() ); + activation.jdk( modelActivation.getJdk() ); org.apache.maven.model.ActivationProperty modelProp = modelActivation.getProperty(); if ( modelProp != null ) { - ActivationProperty prop = new ActivationProperty(); - prop.setName( modelProp.getName() ); - prop.setValue( modelProp.getValue() ); - activation.setProperty( prop ); + ActivationProperty prop = ActivationProperty.newBuilder() + .name( modelProp.getName() ) + .value( modelProp.getValue() ) + .build(); + activation.property( prop ); } org.apache.maven.model.ActivationOS modelOs = modelActivation.getOs(); if ( modelOs != null ) { - ActivationOS os = new ActivationOS(); - - os.setArch( modelOs.getArch() ); - os.setFamily( modelOs.getFamily() ); - os.setName( modelOs.getName() ); - os.setVersion( modelOs.getVersion() ); - - activation.setOs( os ); + ActivationOS os = ActivationOS.newBuilder() + .arch( modelOs.getArch() ) + .family( modelOs.getFamily() ) + .name( modelOs.getName() ) + .version( modelOs.getVersion() ) + .build(); + + activation.os( os ); } - ActivationFile modelFile = modelActivation.getFile(); + org.apache.maven.model.ActivationFile modelFile = modelActivation.getFile(); if ( modelFile != null ) { - org.apache.maven.settings.ActivationFile file = new org.apache.maven.settings.ActivationFile(); + org.apache.maven.api.settings.ActivationFile file + = org.apache.maven.api.settings.ActivationFile.newBuilder() + .exists( modelFile.getExists() ) + .missing( modelFile.getMissing() ) + .build(); - file.setExists( modelFile.getExists() ); - file.setMissing( modelFile.getMissing() ); - - activation.setFile( file ); + activation.file( file ); } - profile.setActivation( activation ); + profile.activation( activation.build() ); } - profile.setProperties( modelProfile.getProperties() ); + profile.properties( modelProfile.getProperties() ); List repos = modelProfile.getRepositories(); if ( repos != null ) { + List repositories = new ArrayList<>(); for ( org.apache.maven.model.Repository repo : repos ) { - profile.addRepository( convertToSettingsRepository( repo ) ); + repositories.add( convertToSettingsRepository( repo ) ); } + profile.repositories( repositories ); } List pluginRepos = modelProfile.getPluginRepositories(); if ( pluginRepos != null ) { + List repositories = new ArrayList<>(); for ( org.apache.maven.model.Repository pluginRepo : pluginRepos ) { - profile.addPluginRepository( convertToSettingsRepository( pluginRepo ) ); + repositories.add( convertToSettingsRepository( pluginRepo ) ); } + profile.pluginRepositories( repositories ); } - return profile; + return profile.build(); } /** @@ -135,121 +150,113 @@ public static Profile convertToSettingsProfile( org.apache.maven.model.Profile m */ public static org.apache.maven.model.Profile convertFromSettingsProfile( Profile settingsProfile ) { - org.apache.maven.model.Profile profile = new org.apache.maven.model.Profile(); - - profile.setId( settingsProfile.getId() ); + org.apache.maven.api.model.Profile.Builder profile = org.apache.maven.api.model.Profile.newBuilder(); - profile.setSource( "settings.xml" ); + profile.id( settingsProfile.getId() ); Activation settingsActivation = settingsProfile.getActivation(); if ( settingsActivation != null ) { - org.apache.maven.model.Activation activation = new org.apache.maven.model.Activation(); + org.apache.maven.api.model.Activation.Builder activation + = org.apache.maven.api.model.Activation.newBuilder(); - activation.setActiveByDefault( settingsActivation.isActiveByDefault() ); + activation.activeByDefault( settingsActivation.isActiveByDefault() ); - activation.setJdk( settingsActivation.getJdk() ); + activation.jdk( settingsActivation.getJdk() ); ActivationProperty settingsProp = settingsActivation.getProperty(); - if ( settingsProp != null ) { - org.apache.maven.model.ActivationProperty prop = new org.apache.maven.model.ActivationProperty(); - - prop.setName( settingsProp.getName() ); - prop.setValue( settingsProp.getValue() ); - - activation.setProperty( prop ); + activation.property( org.apache.maven.api.model.ActivationProperty.newBuilder() + .name( settingsProp.getName() ) + .value( settingsProp.getValue() ) + .build() ); } ActivationOS settingsOs = settingsActivation.getOs(); - if ( settingsOs != null ) { - org.apache.maven.model.ActivationOS os = new org.apache.maven.model.ActivationOS(); - - os.setArch( settingsOs.getArch() ); - os.setFamily( settingsOs.getFamily() ); - os.setName( settingsOs.getName() ); - os.setVersion( settingsOs.getVersion() ); - - activation.setOs( os ); + activation.os( org.apache.maven.api.model.ActivationOS.newBuilder() + .arch( settingsOs.getArch() ) + .family( settingsOs.getFamily() ) + .name( settingsOs.getName() ) + .version( settingsOs.getVersion() ) + .build() ); } - org.apache.maven.settings.ActivationFile settingsFile = settingsActivation.getFile(); - + org.apache.maven.api.settings.ActivationFile settingsFile = settingsActivation.getFile(); if ( settingsFile != null ) { - ActivationFile file = new ActivationFile(); - - file.setExists( settingsFile.getExists() ); - file.setMissing( settingsFile.getMissing() ); - - activation.setFile( file ); + activation.file( ActivationFile.newBuilder() + .exists( settingsFile.getExists() ) + .missing( settingsFile.getMissing() ) + .build() ); } - profile.setActivation( activation ); + profile.activation( activation.build() ); } - profile.setProperties( settingsProfile.getProperties() ); + profile.properties( settingsProfile.getProperties() ); List repos = settingsProfile.getRepositories(); if ( repos != null ) { - for ( Repository repo : repos ) - { - profile.addRepository( convertFromSettingsRepository( repo ) ); - } + profile.repositories( repos.stream() + .map( SettingsUtils::convertFromSettingsRepository ) + .collect( Collectors.toList() ) ); } List pluginRepos = settingsProfile.getPluginRepositories(); if ( pluginRepos != null ) { - for ( Repository pluginRepo : pluginRepos ) - { - profile.addPluginRepository( convertFromSettingsRepository( pluginRepo ) ); - } + profile.pluginRepositories( pluginRepos.stream() + .map( SettingsUtils::convertFromSettingsRepository ) + .collect( Collectors.toList() ) ); } - return profile; + org.apache.maven.model.Profile value = new org.apache.maven.model.Profile( profile.build() ); + value.setSource( "settings.xml" ); + return value; } /** * @param settingsRepo * @return a repository */ - private static org.apache.maven.model.Repository convertFromSettingsRepository( Repository settingsRepo ) + private static org.apache.maven.api.model.Repository convertFromSettingsRepository( Repository settingsRepo ) { - org.apache.maven.model.Repository repo = new org.apache.maven.model.Repository(); + org.apache.maven.api.model.Repository.Builder repo = org.apache.maven.api.model.Repository.newBuilder(); - repo.setId( settingsRepo.getId() ); - repo.setLayout( settingsRepo.getLayout() ); - repo.setName( settingsRepo.getName() ); - repo.setUrl( settingsRepo.getUrl() ); + repo.id( settingsRepo.getId() ); + repo.layout( settingsRepo.getLayout() ); + repo.name( settingsRepo.getName() ); + repo.url( settingsRepo.getUrl() ); if ( settingsRepo.getSnapshots() != null ) { - repo.setSnapshots( convertRepositoryPolicy( settingsRepo.getSnapshots() ) ); + repo.snapshots( convertRepositoryPolicy( settingsRepo.getSnapshots() ) ); } if ( settingsRepo.getReleases() != null ) { - repo.setReleases( convertRepositoryPolicy( settingsRepo.getReleases() ) ); + repo.releases( convertRepositoryPolicy( settingsRepo.getReleases() ) ); } - return repo; + return repo.build(); } /** * @param settingsPolicy * @return a RepositoryPolicy */ - private static org.apache.maven.model.RepositoryPolicy convertRepositoryPolicy( RepositoryPolicy settingsPolicy ) + private static org.apache.maven.api.model.RepositoryPolicy convertRepositoryPolicy( + RepositoryPolicy settingsPolicy ) { - org.apache.maven.model.RepositoryPolicy policy = new org.apache.maven.model.RepositoryPolicy(); - policy.setEnabled( settingsPolicy.isEnabled() ); - policy.setUpdatePolicy( settingsPolicy.getUpdatePolicy() ); - policy.setChecksumPolicy( settingsPolicy.getChecksumPolicy() ); + org.apache.maven.api.model.RepositoryPolicy policy = org.apache.maven.api.model.RepositoryPolicy.newBuilder() + .enabled( Boolean.toString( settingsPolicy.isEnabled() ) ) + .updatePolicy( settingsPolicy.getUpdatePolicy() ) + .checksumPolicy( settingsPolicy.getChecksumPolicy() ) + .build(); return policy; } @@ -259,21 +266,16 @@ private static org.apache.maven.model.RepositoryPolicy convertRepositoryPolicy( */ private static Repository convertToSettingsRepository( org.apache.maven.model.Repository modelRepo ) { - Repository repo = new Repository(); - - repo.setId( modelRepo.getId() ); - repo.setLayout( modelRepo.getLayout() ); - repo.setName( modelRepo.getName() ); - repo.setUrl( modelRepo.getUrl() ); - - if ( modelRepo.getSnapshots() != null ) - { - repo.setSnapshots( convertRepositoryPolicy( modelRepo.getSnapshots() ) ); - } - if ( modelRepo.getReleases() != null ) - { - repo.setReleases( convertRepositoryPolicy( modelRepo.getReleases() ) ); - } + Repository repo = Repository.newBuilder() + .id( modelRepo.getId() ) + .layout( modelRepo.getLayout() ) + .name( modelRepo.getName() ) + .url( modelRepo.getUrl() ) + .snapshots( modelRepo.getSnapshots() != null + ? convertRepositoryPolicy( modelRepo.getSnapshots() ) : null ) + .releases( modelRepo.getReleases() != null + ? convertRepositoryPolicy( modelRepo.getReleases() ) : null ) + .build(); return repo; } @@ -284,38 +286,12 @@ private static Repository convertToSettingsRepository( org.apache.maven.model.Re */ private static RepositoryPolicy convertRepositoryPolicy( org.apache.maven.model.RepositoryPolicy modelPolicy ) { - RepositoryPolicy policy = new RepositoryPolicy(); - policy.setEnabled( modelPolicy.isEnabled() ); - policy.setUpdatePolicy( modelPolicy.getUpdatePolicy() ); - policy.setChecksumPolicy( modelPolicy.getChecksumPolicy() ); + RepositoryPolicy policy = RepositoryPolicy.newBuilder() + .enabled( modelPolicy.isEnabled() ) + .updatePolicy( modelPolicy.getUpdatePolicy() ) + .checksumPolicy( modelPolicy.getUpdatePolicy() ) + .build(); return policy; } - /** - * @param settings could be null - * @return a new instance of settings or null if settings was null. - */ - public static Settings copySettings( Settings settings ) - { - if ( settings == null ) - { - return null; - } - - Settings clone = new Settings(); - clone.setActiveProfiles( settings.getActiveProfiles() ); - clone.setInteractiveMode( settings.isInteractiveMode() ); - clone.setLocalRepository( settings.getLocalRepository() ); - clone.setMirrors( settings.getMirrors() ); - clone.setModelEncoding( settings.getModelEncoding() ); - clone.setOffline( settings.isOffline() ); - clone.setPluginGroups( settings.getPluginGroups() ); - clone.setProfiles( settings.getProfiles() ); - clone.setProxies( settings.getProxies() ); - clone.setServers( settings.getServers() ); - clone.setSourceLevel( settings.getSourceLevel() ); - clone.setUsePluginRegistry( settings.isUsePluginRegistry() ); - - return clone; - } } diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java index 8a90f184702a..bd4df0188ba6 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java @@ -28,7 +28,7 @@ import javax.inject.Singleton; import org.apache.maven.execution.MavenSession; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.slf4j.Logger; /** @@ -58,7 +58,7 @@ public DefaultToolchainManagerPrivate( Map factories ) } @Override - public ToolchainPrivate[] getToolchainsForType( String type, MavenSession context ) + public ToolchainPrivate[] getToolchainsForType( String type, MavenSession session ) throws MisconfiguredToolchainException { List toRet = new ArrayList<>(); @@ -71,13 +71,17 @@ public ToolchainPrivate[] getToolchainsForType( String type, MavenSession contex } else { - List availableToolchains = context.getRequest().getToolchains().get( type ); + List availableToolchains = + org.apache.maven.toolchain.model.ToolchainModel.toolchainModelToApiV4( + session.getRequest().getToolchains().get( type ) ); if ( availableToolchains != null ) { for ( ToolchainModel toolchainModel : availableToolchains ) { - toRet.add( fact.createToolchain( toolchainModel ) ); + org.apache.maven.toolchain.model.ToolchainModel tm = + new org.apache.maven.toolchain.model.ToolchainModel( toolchainModel ); + toRet.add( fact.createToolchain( tm ) ); } } diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java index 84a31e4af58b..619aef6c1213 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java index 115eede3dea6..c99a3cd8ac96 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java @@ -19,6 +19,7 @@ * under the License. */ + import org.apache.maven.toolchain.model.ToolchainModel; /** diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java index 4bb4052a902c..8d4a9787c4d5 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java @@ -21,7 +21,7 @@ import java.io.File; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Builds the toolchains model from a previously configured filesystem path to the toolchains file. diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java index 71d0a0206927..09c721fa88fd 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java @@ -92,8 +92,8 @@ public ToolchainPrivate createToolchain( ToolchainModel model ) } // populate the configuration section - Xpp3Dom dom = (Xpp3Dom) model.getConfiguration(); - Xpp3Dom javahome = dom.getChild( JavaToolchainImpl.KEY_JAVAHOME ); + Xpp3Dom dom = ( Xpp3Dom ) model.getConfiguration(); + Xpp3Dom javahome = dom != null ? dom.getChild( JavaToolchainImpl.KEY_JAVAHOME ) : null; if ( javahome == null ) { throw new MisconfiguredToolchainException( "Java toolchain without the " diff --git a/maven-core/src/main/resources/META-INF/maven/extension.xml b/maven-core/src/main/resources/META-INF/maven/extension.xml index 2fdf4f2be4fb..0acecee57087 100644 --- a/maven-core/src/main/resources/META-INF/maven/extension.xml +++ b/maven-core/src/main/resources/META-INF/maven/extension.xml @@ -22,6 +22,8 @@ under the License. + org.apache.maven.api + org.apache.maven.* org.apache.maven.artifact org.apache.maven.classrealm diff --git a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java index bb3574ae41d8..e8327783df46 100644 --- a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java +++ b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java @@ -22,16 +22,19 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Properties; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.artifact.handler.manager.DefaultArtifactHandlerManager; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.DefaultMavenExecutionResult; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.Exclusion; @@ -48,6 +51,7 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.util.FileUtils; import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.internal.impl.DefaultRepositorySystem; import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; import org.eclipse.aether.repository.LocalRepository; @@ -166,6 +170,9 @@ protected MavenSession createMavenSession( File pom, Properties executionPropert new DefaultMavenExecutionResult() ); session.setProjects( projects ); session.setAllProjects( session.getProjects() ); + session.setSession( new DefaultSession( session, new DefaultRepositorySystem(), null, + null, null, null, null, null, + null, new DefaultArtifactHandlerManager( Collections.emptyMap() ) ) ); return session; } diff --git a/maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java b/maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java new file mode 100644 index 000000000000..c7cf0884b127 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java @@ -0,0 +1,140 @@ +package org.apache.maven.configuration; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.maven.configuration.internal.DefaultBeanConfigurator; +import org.apache.maven.configuration.internal.EnhancedComponentConfigurator; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Benjamin Bentmann + */ +public class DefaultBeanConfiguratorPathTest +{ + + private BeanConfigurator configurator; + + @BeforeEach + public void setUp() + throws Exception + { + configurator = new DefaultBeanConfigurator(); + } + + @AfterEach + public void tearDown() + throws Exception + { + configurator = null; + } + + private Xpp3Dom toConfig( String xml ) + { + try + { + return Xpp3DomBuilder.build( new StringReader( "" + xml + "" ) ); + } + catch ( XmlPullParserException | IOException e ) + { + throw new IllegalArgumentException( e ); + } + } + + @Test + public void testMinimal() + throws BeanConfigurationException + { + SomeBean bean = new SomeBean(); + + Xpp3Dom config = toConfig( "test" ); + + DefaultBeanConfigurationRequest request = new DefaultBeanConfigurationRequest(); + request.setBean( bean ).setConfiguration( config ); + + configurator.configureBean( request ); + + assertEquals( Paths.get( "test" ), bean.file ); + } + + @Test + public void testPreAndPostProcessing() + throws BeanConfigurationException + { + SomeBean bean = new SomeBean(); + + Xpp3Dom config = toConfig( "${test}" ); + + BeanConfigurationValuePreprocessor preprocessor = ( value, type ) -> + { + if ( value != null && value.startsWith( "${" ) && value.endsWith( "}" ) ) + { + return value.substring( 2, value.length() - 1 ); + } + return value; + }; + + BeanConfigurationPathTranslator translator = path -> new File( "base", path.getPath() ).getAbsoluteFile(); + + DefaultBeanConfigurationRequest request = new DefaultBeanConfigurationRequest(); + request.setBean( bean ).setConfiguration( config ); + request.setValuePreprocessor( preprocessor ).setPathTranslator( translator ); + + configurator.configureBean( request ); + + assertEquals( Paths.get( "base/test" ).toAbsolutePath(), bean.file ); + } + + @Test + public void testChildConfigurationElement() + throws BeanConfigurationException + { + SomeBean bean = new SomeBean(); + + Xpp3Dom config = toConfig( "test" ); + + DefaultBeanConfigurationRequest request = new DefaultBeanConfigurationRequest(); + request.setBean( bean ).setConfiguration( config, "wrapper" ); + + configurator.configureBean( request ); + + assertEquals( Paths.get( "test" ), bean.file ); + } + + static class SomeBean + { + + Path file; + + } + +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java new file mode 100644 index 000000000000..f707b543943e --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -0,0 +1,130 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; + +import java.nio.file.Path; +import java.util.Collections; +import java.util.Optional; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectBuilderRequest; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.apache.maven.rtinfo.RuntimeInformation; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.testing.PlexusTest; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.RemoteRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@PlexusTest +public class TestApi +{ + + Session session; + + @Inject + RepositorySystem repositorySystem; + + @Inject + org.apache.maven.project.ProjectBuilder projectBuilder; + + @Inject + MavenRepositorySystem mavenRepositorySystem; + + @Inject + DefaultToolchainManagerPrivate toolchainManagerPrivate; + + @Inject + PlexusContainer plexusContainer; + + @Inject + MojoExecutionScope mojoExecutionScope; + + @Inject + RuntimeInformation runtimeInformation; + + @Inject + ArtifactHandlerManager artifactHandlerManager; + + @BeforeEach + void setup() + { + RepositorySystemSession rss = MavenRepositorySystemUtils.newSession(); + DefaultMavenExecutionRequest mer = new DefaultMavenExecutionRequest(); + MavenSession ms = new MavenSession( null, rss, mer, null ); + DefaultSession session = new DefaultSession( ms, repositorySystem, + Collections.emptyList(), projectBuilder, + mavenRepositorySystem, toolchainManagerPrivate, + plexusContainer, mojoExecutionScope, runtimeInformation, + artifactHandlerManager ); + DefaultLocalRepository localRepository = new DefaultLocalRepository( + new LocalRepository( "target/test-classes/apiv4-repo" ) ); + org.apache.maven.api.RemoteRepository remoteRepository = session.getRemoteRepository( + new RemoteRepository.Builder( "mirror", "default", + "file:target/test-classes/repo" ).build() ); + this.session = session + .withLocalRepository( localRepository ) + .withRemoteRepositories( Collections.singletonList( remoteRepository ) ); + } + + @Test + void testCreateAndResolveArtifact() throws Exception + { + ArtifactCoordinate coord = session.createArtifactCoordinate( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); + + Artifact resolved = session.resolveArtifact( coord ); + Optional op = session.getArtifactPath( resolved ); + assertTrue( op.isPresent() ); + assertNotNull( op.get() ); + + Project project = session.getService( ProjectBuilder.class ).build( + ProjectBuilderRequest.builder().session( session ).path( op.get() ) + .processPlugins( false ).resolveDependencies( false ).build() ) + .getProject().get(); + assertNotNull( project ); + + Artifact artifact = session.createArtifact( "org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar" ); + Node root = session.collectDependencies( artifact ); + assertNotNull( root ); + } + + +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java new file mode 100644 index 000000000000..3db6e830e575 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java @@ -0,0 +1,83 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.artifact.handler.ArtifactHandler; + +/** + * Assists unit testing. + * + * @author Benjamin Bentmann + */ +class TestArtifactHandler + implements ArtifactHandler +{ + + private String type; + + private String extension; + + public TestArtifactHandler( String type ) + { + this( type, type ); + } + + public TestArtifactHandler( String type, String extension ) + { + this.type = type; + this.extension = extension; + } + + public String getClassifier() + { + return null; + } + + public String getDirectory() + { + return getPackaging() + "s"; + } + + public String getExtension() + { + return extension; + } + + public String getLanguage() + { + return "java"; + } + + public String getPackaging() + { + return type; + } + + public boolean isAddedToClasspath() + { + return true; + } + + public boolean isIncludesDependencies() + { + return false; + } + +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java new file mode 100644 index 000000000000..430b27631906 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java @@ -0,0 +1,341 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.model.Model; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; +import org.apache.maven.artifact.repository.MavenArtifactRepository; +import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; +import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Repository; +import org.apache.maven.model.io.ModelReader; +import org.apache.maven.project.artifact.ArtifactWithDependencies; +import org.apache.maven.repository.ArtifactDoesNotExistException; +import org.apache.maven.repository.ArtifactTransferFailedException; +import org.apache.maven.repository.ArtifactTransferListener; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Server; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; +import org.eclipse.aether.RepositorySystemSession; + +/** + * @author Benjamin Bentmann + */ +@Named +@Singleton +public class TestRepositorySystem + implements RepositorySystem +{ + + private final ModelReader modelReader; + + private final ArtifactFactory artifactFactory; + + @Inject + public TestRepositorySystem( ModelReader modelReader, ArtifactFactory artifactFactory ) + { + this.modelReader = modelReader; + this.artifactFactory = artifactFactory; + } + + public ArtifactRepository buildArtifactRepository( Repository repository ) + throws InvalidRepositoryException + { + return new MavenArtifactRepository( repository.getId(), repository.getUrl(), new DefaultRepositoryLayout(), + new ArtifactRepositoryPolicy(), new ArtifactRepositoryPolicy() ); + } + + public Artifact createArtifact( String groupId, String artifactId, String version, String packaging ) + { + return createArtifact( groupId, artifactId, version, null, packaging ); + } + + public Artifact createArtifact( String groupId, String artifactId, String version, String scope, String type ) + { + return new DefaultArtifact( groupId, artifactId, version, scope, type, null, new TestArtifactHandler( type ) ); + } + + public ArtifactRepository createArtifactRepository( String id, String url, + ArtifactRepositoryLayout repositoryLayout, + ArtifactRepositoryPolicy snapshots, + ArtifactRepositoryPolicy releases ) + { + return new MavenArtifactRepository( id, url, repositoryLayout, snapshots, releases ); + } + + public Artifact createArtifactWithClassifier( String groupId, String artifactId, String version, String type, + String classifier ) + { + return new DefaultArtifact( groupId, artifactId, version, null, type, classifier, + new TestArtifactHandler( type ) ); + } + + public ArtifactRepository createDefaultLocalRepository() + throws InvalidRepositoryException + { + return createLocalRepository( new File( System.getProperty( "basedir", "." ), "target/local-repo" ).getAbsoluteFile() ); + } + + public ArtifactRepository createDefaultRemoteRepository() + throws InvalidRepositoryException + { + return new MavenArtifactRepository( DEFAULT_REMOTE_REPO_ID, "file://" + + new File( System.getProperty( "basedir", "." ), "src/test/remote-repo" ).getAbsoluteFile().toURI().getPath(), + new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(), + new ArtifactRepositoryPolicy() ); + } + + public Artifact createDependencyArtifact( Dependency dependency ) + { + Artifact artifact = + new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), + dependency.getScope(), dependency.getType(), dependency.getClassifier(), + new TestArtifactHandler( dependency.getType() ) ); + + if ( Artifact.SCOPE_SYSTEM.equals( dependency.getScope() ) ) + { + artifact.setFile( new File( dependency.getSystemPath() ) ); + artifact.setResolved( true ); + } + + return artifact; + } + + public ArtifactRepository createLocalRepository( File localRepository ) + throws InvalidRepositoryException + { + return new MavenArtifactRepository( DEFAULT_LOCAL_REPO_ID, "file://" + localRepository.toURI().getPath(), + new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(), + new ArtifactRepositoryPolicy() ); + } + + public Artifact createPluginArtifact( Plugin plugin ) + { + VersionRange versionRange; + try + { + String version = plugin.getVersion(); + if ( StringUtils.isEmpty( version ) ) + { + version = "RELEASE"; + } + versionRange = VersionRange.createFromVersionSpec( version ); + } + catch ( InvalidVersionSpecificationException e ) + { + return null; + } + + return artifactFactory.createPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), versionRange ); + } + + public Artifact createProjectArtifact( String groupId, String artifactId, String version ) + { + return createArtifact( groupId, artifactId, version, "pom" ); + } + + public List getEffectiveRepositories( List repositories ) + { + return repositories; + } + + public Mirror getMirror( ArtifactRepository repository, List mirrors ) + { + return null; + } + + public void injectAuthentication( List repositories, List servers ) + { + } + + public void injectMirror( List repositories, List mirrors ) + { + } + + public void injectProxy( List repositories, List proxies ) + { + } + + public void publish( ArtifactRepository repository, File source, String remotePath, + ArtifactTransferListener transferListener ) + throws ArtifactTransferFailedException + { + // TODO Auto-generated method stub + + } + + public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) + { + ArtifactResolutionResult result = new ArtifactResolutionResult(); + + if ( request.isResolveRoot() ) + { + try + { + resolve( request.getArtifact(), request ); + result.addArtifact( request.getArtifact() ); + } + catch ( IOException e ) + { + result.addMissingArtifact( request.getArtifact() ); + } + } + + if ( request.isResolveTransitively() ) + { + Map artifacts = new LinkedHashMap<>(); + + if ( request.getArtifactDependencies() != null ) + { + for ( Artifact artifact : request.getArtifactDependencies() ) + { + artifacts.put( artifact.getDependencyConflictId(), artifact ); + } + } + + List dependencies = new ArrayList<>(); + if ( request.getArtifact() instanceof ArtifactWithDependencies ) + { + dependencies = ( (ArtifactWithDependencies) request.getArtifact() ).getDependencies(); + } + else + { + Artifact pomArtifact = + createProjectArtifact( request.getArtifact().getGroupId(), request.getArtifact().getArtifactId(), + request.getArtifact().getVersion() ); + File pomFile = + new File( request.getLocalRepository().getBasedir(), + request.getLocalRepository().pathOf( pomArtifact ) ); + + try + { + Model model = modelReader.read( pomFile, null ); + + dependencies = Dependency.dependencyToApiV3( model.getDependencies() ); + } + catch ( IOException e ) + { + e.printStackTrace(); + } + } + + for ( Dependency dependency : dependencies ) + { + Artifact artifact = createDependencyArtifact( dependency ); + if ( !artifacts.containsKey( artifact.getDependencyConflictId() ) ) + { + artifacts.put( artifact.getDependencyConflictId(), artifact ); + } + } + + for ( Artifact artifact : artifacts.values() ) + { + try + { + resolve( artifact, request ); + result.addArtifact( artifact ); + } + catch ( IOException e ) + { + result.addMissingArtifact( artifact ); + } + } + } + + return result; + } + + private void resolve( Artifact artifact, ArtifactResolutionRequest request ) + throws IOException + { + if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) ) + { + return; + } + + ArtifactRepository localRepo = request.getLocalRepository(); + + File localFile = new File( localRepo.getBasedir(), localRepo.pathOf( artifact ) ); + + artifact.setFile( localFile ); + + if ( !localFile.exists() ) + { + if ( request.getRemoteRepositories().isEmpty() ) + { + throw new IOException( localFile + " does not exist and no remote repositories are configured" ); + } + + ArtifactRepository remoteRepo = request.getRemoteRepositories().get( 0 ); + + File remoteFile = new File( remoteRepo.getBasedir(), remoteRepo.pathOf( artifact ) ); + + FileUtils.copyFile( remoteFile, localFile ); + } + + artifact.setResolved( true ); + } + + public void retrieve( ArtifactRepository repository, File destination, String remotePath, + ArtifactTransferListener transferListener ) + throws ArtifactTransferFailedException, ArtifactDoesNotExistException + { + // TODO Auto-generated method stub + + } + + public void injectMirror( RepositorySystemSession session, List repositories ) + { + } + + public void injectProxy( RepositorySystemSession session, List repositories ) + { + } + + public void injectAuthentication( RepositorySystemSession session, List repositories ) + { + } + +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java index 4daf735b2774..2841887f90f5 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.maven.AbstractCoreMavenComponentTestCase; +import org.apache.maven.api.xml.Dom; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; @@ -41,7 +42,6 @@ import org.apache.maven.plugin.MojoNotFoundException; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -291,7 +291,7 @@ public void testPluginConfigurationCreation() MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( "org.apache.maven.its.plugins:maven-it-plugin:0.1:java", session, session.getCurrentProject() ); - Xpp3Dom dom = MojoDescriptorCreator.convert( mojoDescriptor ); + Dom dom = MojoDescriptorCreator.convert( mojoDescriptor ); System.out.println( dom ); } diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java index 80770d592434..76fe0122e8d0 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java @@ -16,6 +16,7 @@ package org.apache.maven.lifecycle.internal.stub; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.lifecycle.DefaultLifecycles; import org.apache.maven.lifecycle.LifecycleNotFoundException; import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException; @@ -40,7 +41,6 @@ import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import org.codehaus.plexus.util.xml.Xpp3Dom; import java.util.ArrayList; import java.util.Arrays; diff --git a/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java b/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java index 55b29b67ec83..da2ae4c8fabb 100644 --- a/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java +++ b/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java @@ -90,7 +90,7 @@ private Plugin newPlugin( String artifactId, String... goals ) { PluginExecution pluginExecution = new PluginExecution(); pluginExecution.setId( "default-" + goal ); - pluginExecution.addGoal( goal ); + pluginExecution.setGoals( Collections.singletonList( goal ) ); plugin.addExecution( pluginExecution ); } diff --git a/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java b/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java index 709b88cba365..f0ef5585e882 100644 --- a/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.model.Dependency; @@ -69,7 +70,7 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() thro UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertThat( e.getMessage(), startsWith( "Could not find artifact org.apache:apache:pom:0 in central" ) ); @@ -85,7 +86,7 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNoMatchingVersi UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "No versions matched the requested parent version range '[2.0,2.1)'", e.getMessage() ); @@ -101,7 +102,7 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenUsingRangesWith UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested parent version range '[1,)' does not specify an upper bound", e.getMessage() ); @@ -115,7 +116,7 @@ public void testResolveParentSuccessfullyResolvesExistingParentWithoutRange() th parent.setArtifactId( "apache" ); parent.setVersion( "1" ); - assertNotNull( this.newModelResolver().resolveModel( parent ) ); + assertNotNull( this.newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ) ); assertEquals( "1", parent.getVersion() ); } @@ -127,8 +128,9 @@ public void testResolveParentSuccessfullyResolvesExistingParentUsingHighestVersi parent.setArtifactId( "apache" ); parent.setVersion( "(,2.0)" ); - assertNotNull( this.newModelResolver().resolveModel( parent ) ); - assertEquals( "1", parent.getVersion() ); + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( parent.getDelegate(), modified ) ); + assertEquals( "1", modified.get().getVersion() ); } @Test @@ -141,7 +143,7 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertThat( e.getMessage(), startsWith( "Could not find artifact org.apache:apache:pom:0 in central" ) ); @@ -157,7 +159,7 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNoMatchingV UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "No versions matched the requested dependency version range '[2.0,2.1)'", e.getMessage() ); @@ -173,7 +175,7 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenUsingRanges UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested dependency version range '[1,)' does not specify an upper bound", e.getMessage() ); @@ -187,7 +189,7 @@ public void testResolveDependencySuccessfullyResolvesExistingDependencyWithoutRa dependency.setArtifactId( "apache" ); dependency.setVersion( "1" ); - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); + assertNotNull( this.newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ) ); assertEquals( "1", dependency.getVersion() ); } @@ -199,8 +201,9 @@ public void testResolveDependencySuccessfullyResolvesExistingDependencyUsingHigh dependency.setArtifactId( "apache" ); dependency.setVersion( "(,2.0)" ); - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); - assertEquals( "1", dependency.getVersion() ); + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( dependency.getDelegate(), modified ) ); + assertEquals( "1", modified.get().getVersion() ); } private ModelResolver newModelResolver() throws Exception diff --git a/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java b/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java index ec15951059a3..621cf5fb94bd 100644 --- a/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java @@ -259,6 +259,8 @@ public void testPluginDependenciesInfluenceSorting() build.addPlugin( plugin ); + declaringProject.getModel().setBuild( build ); + projects = new ProjectSorter( projects ).getSortedProjects(); assertEquals( parentProject, projects.get( 0 ) ); diff --git a/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java b/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java index f966237c33d9..8330c3c294f4 100644 --- a/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.List; +import org.apache.maven.api.xml.Dom; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.apache.maven.project.AbstractMavenProjectTestCase; @@ -76,7 +77,7 @@ public void testProjectBuilder() assertEquals( "1.0", plugin.getVersion() ); - Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration(); + Dom configuration = plugin.getDelegate().getConfiguration(); assertEquals( "src/conf/plexus.conf", configuration.getChild( "plexusConfiguration" ).getValue() ); @@ -97,7 +98,7 @@ public void testProjectBuilder() assertEquals( "plexus:runtime", g0 ); - configuration = (Xpp3Dom) execution.getConfiguration(); + configuration = execution.getDelegate().getConfiguration(); assertEquals( "ContinuumPro", configuration.getChild( "plexusApplicationName" ).getValue() ); diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java index 9b204b24dc49..c596a06d3c40 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java @@ -19,15 +19,14 @@ * under the License. */ -import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.apache.commons.jxpath.ri.QName; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.internal.xml.Xpp3Dom; /** * An attribute iterator for JXPath to support Xpp3Dom. @@ -35,7 +34,7 @@ * @author Benjamin Bentmann */ class Xpp3DomAttributeIterator - implements NodeIterator + implements NodeIterator { private NodePointer parent; @@ -53,16 +52,9 @@ public Xpp3DomAttributeIterator( NodePointer parent, QName qname ) this.parent = parent; this.node = (Xpp3Dom) parent.getNode(); - Map map = new LinkedHashMap<>(); - for ( String name : this.node.getAttributeNames() ) - { - if ( name.equals( qname.getName() ) || "*".equals( qname.getName() ) ) - { - String value = this.node.getAttribute( name ); - map.put( name, value ); - } - } - this.attributes = new ArrayList<>( map.entrySet() ); + this.attributes = this.node.getAttributes().entrySet().stream() + .filter( a -> a.getKey().equals( qname.getName() ) || "*".equals( qname.getName() ) ) + .collect( Collectors.toList() ); } public NodePointer getNodePointer() @@ -86,4 +78,4 @@ public boolean setPosition( int position ) return attribute != null; } -} +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java index d137af548a80..6890cc77ddb0 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java @@ -28,6 +28,7 @@ import org.apache.commons.jxpath.ri.compiler.NodeTypeTest; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; +import org.apache.maven.api.xml.Dom; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; @@ -44,29 +45,29 @@ class Xpp3DomNodeIterator private NodeTest test; - private Xpp3Dom node; + private Dom node; - private Xpp3Dom[] children; + private List children; - private List filteredChildren = new ArrayList<>(); + private List filteredChildren = new ArrayList<>(); private int filteredIndex; - private Xpp3Dom child; + private Dom child; private int position; public Xpp3DomNodeIterator( NodePointer parent, NodeTest test, boolean reverse, NodePointer startWith ) { this.parent = parent; - this.node = (Xpp3Dom) parent.getNode(); + this.node = (Dom) parent.getNode(); this.children = this.node.getChildren(); if ( startWith != null ) { Xpp3Dom startWithNode = (Xpp3Dom) startWith.getNode(); - for ( ; filteredIndex < children.length; filteredIndex++ ) + for ( ; filteredIndex < children.size(); filteredIndex++ ) { - if ( startWithNode.equals( children[filteredIndex] ) ) + if ( startWithNode.equals( children.get(filteredIndex) ) ) { filteredIndex++; break; @@ -104,9 +105,9 @@ public boolean setPosition( int position ) private void filterChildren( int position ) { - for ( ; position > filteredChildren.size() && filteredIndex < children.length; filteredIndex++ ) + for ( ; position > filteredChildren.size() && filteredIndex < children.size(); filteredIndex++ ) { - Xpp3Dom child = children[filteredIndex]; + Dom child = children.get(filteredIndex); if ( testNode( child ) ) { filteredChildren.add( child ); @@ -114,7 +115,7 @@ private void filterChildren( int position ) } } - private boolean testNode( Xpp3Dom node ) + private boolean testNode( Dom node ) { if ( test == null ) { diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java index 19defa142d87..81060b08dac6 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java @@ -26,7 +26,7 @@ import org.apache.commons.jxpath.ri.compiler.NodeTest; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; /** * A node pointer for JXPath to support Xpp3Dom. @@ -37,15 +37,15 @@ class Xpp3DomNodePointer extends NodePointer { - private Xpp3Dom node; + private Dom node; - public Xpp3DomNodePointer( Xpp3Dom node ) + public Xpp3DomNodePointer( Dom node ) { super( null ); this.node = node; } - public Xpp3DomNodePointer( NodePointer parent, Xpp3Dom node ) + public Xpp3DomNodePointer( NodePointer parent, Dom node ) { super( parent ); this.node = node; @@ -54,15 +54,14 @@ public Xpp3DomNodePointer( NodePointer parent, Xpp3Dom node ) @Override public int compareChildNodePointers( NodePointer pointer1, NodePointer pointer2 ) { - Xpp3Dom node1 = (Xpp3Dom) pointer1.getBaseValue(); - Xpp3Dom node2 = (Xpp3Dom) pointer2.getBaseValue(); + Dom node1 = (Dom) pointer1.getBaseValue(); + Dom node2 = (Dom) pointer2.getBaseValue(); if ( node1 == node2 ) { return 0; } - for ( int i = 0; i < node.getChildCount(); i++ ) + for ( Dom child : node.getChildren() ) { - Xpp3Dom child = node.getChild( i ); if ( child == node1 ) { return -1; @@ -81,7 +80,7 @@ public Object getValue() return getValue( node ); } - private static Object getValue( Xpp3Dom node ) + private static Object getValue( Dom node ) { if ( node.getValue() != null ) { @@ -90,9 +89,9 @@ private static Object getValue( Xpp3Dom node ) else { List children = new ArrayList<>(); - for ( int i = 0; i < node.getChildCount(); i++ ) + for ( Dom child : node.getChildren() ) { - children.add( getValue( node.getChild( i ) ) ); + children.add( getValue( child ) ); } return children; } @@ -131,7 +130,7 @@ public boolean isCollection() @Override public boolean isLeaf() { - return node.getChildCount() <= 0; + return node.getChildren().isEmpty(); } @Override diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java index 28c0f8ff5d1c..24aab57dcc68 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java @@ -24,7 +24,7 @@ import org.apache.commons.jxpath.ri.QName; import org.apache.commons.jxpath.ri.model.NodePointer; import org.apache.commons.jxpath.ri.model.NodePointerFactory; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; /** * A node pointer factory for JXPath to support Xpp3Dom. @@ -42,18 +42,26 @@ public int getOrder() public NodePointer createNodePointer( QName name, Object object, Locale locale ) { - if ( object instanceof Xpp3Dom ) + if ( object instanceof org.codehaus.plexus.util.xml.Xpp3Dom ) { - return new Xpp3DomNodePointer( (Xpp3Dom) object ); + object = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) object ).getDom(); + } + if ( object instanceof Dom ) + { + return new Xpp3DomNodePointer( (Dom) object ); } return null; } public NodePointer createNodePointer( NodePointer parent, QName name, Object object ) { - if ( object instanceof Xpp3Dom ) + if ( object instanceof org.codehaus.plexus.util.xml.Xpp3Dom ) + { + object = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) object ).getDom(); + } + if ( object instanceof Dom ) { - return new Xpp3DomNodePointer( parent, (Xpp3Dom) object ); + return new Xpp3DomNodePointer( parent, (Dom) object ); } return null; } diff --git a/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java b/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java index c95f42843f5e..7fdaef8d5de8 100644 --- a/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java +++ b/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java @@ -25,6 +25,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; @@ -44,7 +45,7 @@ import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.Repository; import org.apache.maven.model.io.ModelReader; @@ -249,7 +250,7 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) { Model model = modelReader.read( pomFile, null ); - dependencies = model.getDependencies(); + dependencies = model.getDependencies().stream().map( Dependency::new ).collect( Collectors.toList() ); } catch ( IOException e ) { diff --git a/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java b/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java index e13382b53224..9b16403e5b86 100644 --- a/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java +++ b/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java @@ -112,7 +112,7 @@ private PomTestWrapper buildPom( String pomPath ) for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) { - Profile profile = SettingsUtils.convertFromSettingsProfile( rawProfile ); + Profile profile = SettingsUtils.convertFromSettingsProfile( rawProfile.getDelegate() ); config.addProfile( profile ); } diff --git a/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java b/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java index 6943c342385d..bdbdad78a89e 100644 --- a/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java +++ b/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java @@ -20,10 +20,18 @@ */ import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.Random; +import org.apache.maven.api.settings.Activation; +import org.apache.maven.api.settings.ActivationFile; +import org.apache.maven.api.settings.ActivationOS; +import org.apache.maven.api.settings.ActivationProperty; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.Settings; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -35,16 +43,17 @@ public class SettingsUtilsTest @Test public void testShouldAppendRecessivePluginGroupIds() { - Settings dominant = new Settings(); - dominant.addPluginGroup( "org.apache.maven.plugins" ); - dominant.addPluginGroup( "org.codehaus.modello" ); + Settings dominant = Settings.newBuilder() + .pluginGroups( Arrays.asList( "org.apache.maven.plugins", "org.codehaus.modello" ) ) + .build(); - Settings recessive = new Settings(); - recessive.addPluginGroup( "org.codehaus.plexus" ); + Settings recessive = Settings.newBuilder() + .pluginGroups( Arrays.asList( "org.codehaus.plexus" ) ) + .build(); - SettingsUtils.merge( dominant, recessive, Settings.GLOBAL_LEVEL ); + Settings merged = SettingsUtils.merge( dominant, recessive, Settings.GLOBAL_LEVEL ); - List pluginGroups = dominant.getPluginGroups(); + List pluginGroups = merged.getPluginGroups(); assertNotNull( pluginGroups ); assertEquals( 3, pluginGroups.size() ); @@ -57,56 +66,63 @@ public void testShouldAppendRecessivePluginGroupIds() public void testRoundTripProfiles() { Random entropy = new Random(); - Profile p = new Profile(); - p.setId( "id" + Long.toHexString( entropy.nextLong() ) ); - Activation a = new Activation(); - a.setActiveByDefault( entropy.nextBoolean() ); - a.setJdk( "jdk" + Long.toHexString( entropy.nextLong() ) ); - ActivationFile af = new ActivationFile(); - af.setExists( "exists" + Long.toHexString( entropy.nextLong() ) ); - af.setMissing( "missing" + Long.toHexString( entropy.nextLong() ) ); - a.setFile( af ); - ActivationProperty ap = new ActivationProperty(); - ap.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - ap.setValue( "value" + Long.toHexString( entropy.nextLong() ) ); - a.setProperty( ap ); - ActivationOS ao = new ActivationOS(); - ao.setArch( "arch" + Long.toHexString( entropy.nextLong() ) ); - ao.setFamily( "family" + Long.toHexString( entropy.nextLong() ) ); - ao.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - ao.setVersion( "version" + Long.toHexString( entropy.nextLong() ) ); - a.setOs( ao ); - p.setActivation( a ); + ActivationFile af = ActivationFile.newBuilder() + .exists( "exists" + Long.toHexString( entropy.nextLong() ) ) + .missing( "missing" + Long.toHexString( entropy.nextLong() ) ) + .build(); + ActivationProperty ap = ActivationProperty.newBuilder() + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .value( "value" + Long.toHexString( entropy.nextLong() ) ) + .build(); + ActivationOS ao = ActivationOS.newBuilder() + .arch( "arch" + Long.toHexString( entropy.nextLong() ) ) + .family( "family" + Long.toHexString( entropy.nextLong() ) ) + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .version( "version" + Long.toHexString( entropy.nextLong() ) ) + .build(); + Activation a = Activation.newBuilder() + .activeByDefault( entropy.nextBoolean() ) + .jdk( "jdk" + Long.toHexString( entropy.nextLong() ) ) + .file( af ) + .property( ap ) + .os( ao ) + .build(); Properties props = new Properties(); int count = entropy.nextInt( 10 ); for ( int i = 0; i < count; i++ ) { props.setProperty( "name" + Long.toHexString( entropy.nextLong() ), - "value" + Long.toHexString( entropy.nextLong() ) ); + "value" + Long.toHexString( entropy.nextLong() ) ); } - p.setProperties( props ); count = entropy.nextInt( 3 ); List repos = new ArrayList<>(); for ( int i = 0; i < count; i++ ) { - Repository r = new Repository(); - r.setId( "id" + Long.toHexString( entropy.nextLong() ) ); - r.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - r.setUrl( "url" + Long.toHexString( entropy.nextLong() ) ); + Repository r = Repository.newBuilder() + .id( "id" + Long.toHexString( entropy.nextLong() ) ) + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .url( "url" + Long.toHexString( entropy.nextLong() ) ) + .build(); repos.add( r ); } - p.setRepositories( repos ); count = entropy.nextInt( 3 ); - repos = new ArrayList<>(); + List pluginRepos = new ArrayList<>(); for ( int i = 0; i < count; i++ ) { - Repository r = new Repository(); - r.setId( "id" + Long.toHexString( entropy.nextLong() ) ); - r.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - r.setUrl( "url" + Long.toHexString( entropy.nextLong() ) ); - repos.add( r ); + Repository r = Repository.newBuilder() + .id( "id" + Long.toHexString( entropy.nextLong() ) ) + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .url( "url" + Long.toHexString( entropy.nextLong() ) ) + .build(); + pluginRepos.add( r ); } - p.setPluginRepositories( repos ); + Profile p = Profile.newBuilder() + .id( "id" + Long.toHexString( entropy.nextLong() ) ) + .activation( a ) + .properties( props ) + .repositories( repos ) + .pluginRepositories( pluginRepos ) + .build(); Profile clone = SettingsUtils.convertToSettingsProfile( SettingsUtils.convertFromSettingsProfile( p ) ); @@ -127,4 +143,4 @@ public void testRoundTripProfiles() // TODO deep compare the lists } -} +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java index 8b2605af2f53..893f55f044cd 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java @@ -45,7 +45,7 @@ public class DefaultToolchainManagerTest { - // Mocks to inject into toolchainManager + // Mocks to inject into toolchainManager @Mock private Logger logger; @@ -131,7 +131,7 @@ public void testModelsAndFactory() @Test public void testRequirements() - throws Exception + throws Exception { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); @@ -145,8 +145,8 @@ public void testRequirements() when( toolchainFactory_basicType.createToolchain( isA( ToolchainModel.class ) ) ).thenReturn( basicPrivate ); List toolchains = - toolchainManager.getToolchains( session, "basic", Collections.singletonMap( "key", "value" ) ); + toolchainManager.getToolchains( session, "basic", Collections.singletonMap( "key", "value" ) ); assertEquals( 1, toolchains.size() ); } -} +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java index f335003a5489..509e014a2375 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java @@ -41,7 +41,7 @@ public class DefaultToolchainTest @BeforeEach public void setUp() - throws Exception + throws Exception { MockitoAnnotations.initMocks( this ); } @@ -154,4 +154,4 @@ public void testEquals() assertNotEquals( tc2, tc1 ); assertEquals( tc2, tc2 ); } -} +} \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar new file mode 100644 index 000000000000..b99c9375a488 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar.sha1 new file mode 100644 index 000000000000..9e50b2572374 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar.sha1 @@ -0,0 +1 @@ +760c711c71588bc273d3e56d196d720a7678cd93 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom new file mode 100644 index 000000000000..c46b27ffb6ae --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom @@ -0,0 +1,31 @@ + + 4.0.0 + commons-logging + commons-logging + Logging + 1.0.3 + Commons Logging + http://jakarta.apache.org/commons/logging/ + 2001 + + + + log4j + log4j + 1.2.6 + true + + + logkit + logkit + 1.0.1 + true + + + junit + junit + 3.7 + test + + + diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 new file mode 100644 index 000000000000..d135fea10f95 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 @@ -0,0 +1 @@ +b7de43bb310eb1dbfd00a34cec30500fa13cb577 /home/projects/maven/repository-staging/to-ibiblio/maven2/commons-logging/commons-logging/1.0.3/commons-logging-1.0.3.pom diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated new file mode 100644 index 000000000000..6dcdbc779638 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Thu Sep 24 16:40:08 CEST 2020 +https\://repo.maven.apache.org/maven2/.lastUpdated=1600958408640 +https\://repo.maven.apache.org/maven2/.error= diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar new file mode 100644 index 000000000000..b73a80fab641 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar.sha1 new file mode 100644 index 000000000000..7e0a60e4f55d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar.sha1 @@ -0,0 +1 @@ +f029a2aefe2b3e1517573c580f948caac31b1056 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom new file mode 100644 index 000000000000..7c1017dc2a3e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom @@ -0,0 +1,165 @@ + + 4.0.0 + commons-logging + commons-logging + Logging + 1.0.4 + Commons Logging is a thin adapter allowing configurable bridging to other, + well known logging systems. + http://jakarta.apache.org/commons/logging/ + + http://issues.apache.org/bugzilla/ + + + + + +
commons-dev@jakarta.apache.org
+
+
+
+
+ 2001 + + + Commons Dev List + commons-dev-subscribe@jakarta.apache.org + commons-dev-unsubscribe@jakarta.apache.org + http://nagoya.apache.org/eyebrowse/SummarizeList?listName=commons-dev@jakarta.apache.org + + + Commons User List + commons-user-subscribe@jakarta.apache.org + commons-user-unsubscribe@jakarta.apache.org + http://nagoya.apache.org/eyebrowse/SummarizeList?listName=commons-user@jakarta.apache.org + + + + + morgand + Morgan Delagrange + morgand at apache dot org + Apache + + Java Developer + + + + rwaldhoff + Rodney Waldhoff + rwaldhoff at apache org + Apache Software Foundation + + + craigmcc + Craig McClanahan + craigmcc at apache org + Apache Software Foundation + + + sanders + Scott Sanders + sanders at apache dot org + Apache Software Foundation + + + rdonkin + Robert Burrell Donkin + rdonkin at apache dot org + Apache Software Foundation + + + donaldp + Peter Donald + donaldp at apache dot org + + + + costin + Costin Manolache + costin at apache dot org + Apache Software Foundation + + + rsitze + Richard Sitze + rsitze at apache dot org + Apache Software Foundation + + + baliuka + Juozas Baliuka + baliuka@apache.org + + + Java Developer + + + + + + The Apache Software License, Version 2.0 + /LICENSE.txt + + + + scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-commons/logging + http://cvs.apache.org/viewcvs/jakarta-commons/logging/ + + + The Apache Software Foundation + http://jakarta.apache.org + + + src/java + src/test + + + maven-surefire-plugin + + + **/AvalonLoggerTest.java + + + + + + + + log4j + log4j + 1.2.6 + true + + + logkit + logkit + 1.0.1 + true + + + junit + junit + 3.7 + test + + + avalon-framework + avalon-framework + 4.1.3 + true + + + + + default + Default Repository + file:///www/jakarta.apache.org/builds/jakarta-commons/logging/ + + + default + Default Site + scp://jakarta.apache.org//www/jakarta.apache.org/commons/logging/ + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 new file mode 100644 index 000000000000..92265fb19772 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 @@ -0,0 +1 @@ +7d32e7520b801cabc3dc704d2afe59d020d00c45 /home/projects/maven/repository-staging/to-ibiblio/maven2/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.pom diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom new file mode 100644 index 000000000000..9593e9e74def --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom @@ -0,0 +1,82 @@ + + + + + + 4.0.0 + + + org.apache + apache + 3 + pom + The Apache Software Foundation + + The Apache Software Foundation provides support for the Apache community of open-source software projects. + The Apache projects are characterized by a collaborative, consensus based development process, an open and + pragmatic software license, and a desire to create high quality software that leads the way in its field. + We consider ourselves not simply a group of projects sharing a server, but rather a community of developers + and users. + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + Apache Software Foundation + http://www.apache.org/ + + http://www.apache.org/ + + + apache.snapshots + Apache Snapshot Repository + http://people.apache.org/repo/m2-snapshot-repository + + false + + + + + + + apache.releases + Apache Release Distribution Repository + scp://people.apache.org/www/people.apache.org/repo/m2-ibiblio-rsync-repository + + + apache.snapshots + Apache Development Snapshot Repository + scp://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository + + + + + Apache Announce List + announce-subscribe@apache.org + announce-unsubscribe@apache.org + announce@apache.org + http://mail-archives.apache.org/mod_mbox/www-announce/ + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 new file mode 100644 index 000000000000..b9d0ea16a252 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 @@ -0,0 +1 @@ +c857ebbb5f303f435495e40e6c9e45a2 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 new file mode 100644 index 000000000000..ffb57bbc8b4f --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 @@ -0,0 +1 @@ +1bc0010136a890e2fd38d901a0b7ecdf0e3f9871 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar new file mode 100644 index 000000000000..5bc9c06cc690 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.md5 new file mode 100644 index 000000000000..5ff89e832f36 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.md5 @@ -0,0 +1 @@ +430da483dcfb2964a9dcd619c29a6c78 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.sha1 new file mode 100644 index 000000000000..a3418804d3c4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.sha1 @@ -0,0 +1 @@ +ea9e3f3fdc25f386d5f9ac861a55b6c3bb773d91 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom new file mode 100644 index 000000000000..4c344c836fa7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom @@ -0,0 +1,112 @@ + + + + + + + maven-parent + org.apache.maven + 5 + + 4.0.0 + org.apache.maven.artifact + maven-artifact + 3.0-SNAPSHOT + Maven Artifact + + scm:svn:http://svn.apache.org/repos/asf/maven/artifact/trunk + scm:svn:https://svn.apache.org/repos/asf/maven/artifact/trunk + http://svn.apache.org/viewcvs.cgi/maven/artifact/trunk + + + + org.codehaus.plexus + plexus-utils + 1.4.5 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-32 + + + org.codehaus.plexus + plexus-active-collections + 1.0-beta-1 + + + org.apache.maven.wagon + wagon-provider-api + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-file + 1.0-beta-2 + test + + + easymock + easymock + 1.2_Java1.3 + test + + + + + + org.codehaus.modello + modello-maven-plugin + 1.0-alpha-17 + + 1.0.0 + src/main/mdo/metadata.mdo + + + + site-docs + pre-site + + xdoc + xsd + + + + standard + + java + xpp3-reader + xpp3-writer + + + + + + maven-surefire-plugin + + + **/testutils/** + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 new file mode 100644 index 000000000000..11e353631a78 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 @@ -0,0 +1 @@ +794377b5385c68c660ee9ca26e6b5cf1 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 new file mode 100644 index 000000000000..4beb688de1a2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 @@ -0,0 +1 @@ +358254e73f075bcfb9d587d0da553083abd0cc45 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.jar new file mode 100644 index 000000000000..0272ee3cd22e Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom new file mode 100644 index 000000000000..fee83c92a1e6 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom @@ -0,0 +1,73 @@ + + 4.0.0 + org.apache.maven.core.test + test-extension + jar + 1 + test-extension + + + + org.apache.maven.artifact + maven-artifact + 3.0-SNAPSHOT + + + org.codehaus.plexus + plexus-utils + 1.1 + + + org.codehaus.plexus + plexus + 1.0.11 + pom + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-16 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-16 + + + + + + + maven-assembly-plugin + 2.2-beta-2-SNAPSHOT + + + repo-assembly + package + + single + + + + repo.xml + + test-extension + true + ${pom.basedir}/../../resources/org/apache/maven/extension + true + + + + + + + + + + dummy + file:///tmp/dummy-repo + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 new file mode 100644 index 000000000000..ad06718cdc09 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 @@ -0,0 +1 @@ +e8f6e0f4ef9c2ed3fb185ef44165fb40 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 new file mode 100644 index 000000000000..6065ee045257 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 @@ -0,0 +1 @@ +88ace5d78ee32fa0ce59714a4a42a73af3b52bd3 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.jar new file mode 100644 index 000000000000..04fe3846962d Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom new file mode 100644 index 000000000000..01aaa425c550 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom @@ -0,0 +1,44 @@ + + 4.0.0 + org.apache.maven.core.test + test-lifecycle-and-artifactHandler + jar + 1 + test-lifecycle-and-artifactHandler + + + + + maven-assembly-plugin + 2.2-beta-2-SNAPSHOT + + + repo-assembly + package + + single + + + + repo.xml + + test-extension + true + ${pom.basedir}/../../resources/org/apache/maven/extension + true + + + + + + + + + + dummy + file:///tmp/dummy-repo + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 new file mode 100644 index 000000000000..01d519420257 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 @@ -0,0 +1 @@ +7f10427af029d20cbea57c21d1aec65e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 new file mode 100644 index 000000000000..dac1e45a9db7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 @@ -0,0 +1 @@ +ed98c808239aefb0ec51a8b9e96f191da7fd92e6 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom new file mode 100644 index 000000000000..b41037fc7382 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom @@ -0,0 +1,304 @@ + + + + + + 4.0.0 + + org.apache + apache + 3 + ../asf/pom.xml + + org.apache.maven + maven-parent + 4 + pom + Apache Maven + + Maven is a software project management and comprehension tool. Based on the concept of a project object model + (POM), Maven can manage a project's build, reporting and documentation from a central piece of information. + + http://maven.apache.org/ + + jira + http://jira.codehaus.org/browse/MPA + + + continuum + http://maven.zones.apache.org:8080/continuum + + + mail + +
notifications@maven.apache.org
+
+
+
+
+ 2002 + + + Maven Announcements List + announce@maven.apache.org + announce-subscribe@maven.apache.org + announce-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-announce/ + + + Maven Issues List + issues@maven.apache.org + issues-subscribe@maven.apache.org + issues-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-issues/ + + + Maven Notifications List + notifications@maven.apache.org + notifications-subscribe@maven.apache.org + notifications-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-notifications/ + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + ASF + + PMC Chair + + -5 + + + brett + Brett Porter + brett@apache.org + ASF + + PMC Member + + +10 + + + evenisse + Emmanuel Venisse + evenisse@apache.org + ASF + + PMC Member + + +1 + + + kenney + Kenney Westerhof + kenney@apache.org + Neonics + + PMC Member + + + + snicoll + Stephane Nicoll + snicoll@apache.org + ASF + + PMC Member + + +1 + + + vmassol + Vincent Massol + vmassol@apache.org + ASF + + PMC Member + + +1 + + + fgiust + Fabrizio Giustina + fgiust@apache.org + openmind + + PMC Member + + +1 + + + epunzalan + Edwin Punzalan + epunzalan@mergere.com + Mergere + + Committer + + +8 + + + mperham + Mike Perham + mperham@gmail.com + IBM + + PMC Member + + -6 + + + jdcasey + John Casey + jdcasey@apache.org + ASF + + PMC Member + + -5 + + + trygvis + Trygve Laugstol + trygvis@apache.org + ASF + + PMC Member + + +1 + + + vsiveton + Vincent Siveton + vsiveton@apache.org + ASF + + PMC Member + + -5 + + + carlos + Carlos Sanchez + carlos@apache.org + ASF + + PMC Member + + +1 + + + dennisl + Dennis Lundberg + dennisl@apache.org + ASF + + PMC Member + + +1 + + + + + + apache.website + scp://people.apache.org/www/maven.apache.org + + + + + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven_checks.xml + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven-header.txt + + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.codehaus.mojo + cobertura-maven-plugin + + + org.codehaus.mojo + taglist-maven-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + + + scm:svn:http://svn.apache.org/repos/asf/maven/pom/maven/tags/maven-parent-4 + scm:svn:https://svn.apache.org/repos/asf/maven/pom/maven/tags/maven-parent-4 + http://svn.apache.org/viewvc/maven/pom/maven/tags/maven-parent-4 + +
+ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 new file mode 100644 index 000000000000..9c417645ed8d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 @@ -0,0 +1 @@ +2a4e926f3a76c6e74b0b126f513ad4e7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 new file mode 100644 index 000000000000..b6caacf5e416 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 @@ -0,0 +1 @@ +0fc039b0bd4d17d7c147a30e1d83994629c5297c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom new file mode 100644 index 000000000000..a512366b97f9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom @@ -0,0 +1,466 @@ + + + + + + 4.0.0 + + org.apache + apache + 3 + ../asf/pom.xml + + org.apache.maven + maven-parent + 5 + pom + Apache Maven + + Maven is a software project management and comprehension tool. Based on the concept of a project object model + (POM), Maven can manage a project's build, reporting and documentation from a central piece of information. + + http://maven.apache.org/ + + jira + http://jira.codehaus.org/browse/MPA + + + continuum + http://maven.zones.apache.org/continuum + + + mail + +
notifications@maven.apache.org
+
+
+
+
+ 2002 + + + Maven Announcements List + announce@maven.apache.org + announce-subscribe@maven.apache.org + announce-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-announce/ + + + Maven Issues List + issues@maven.apache.org + issues-subscribe@maven.apache.org + issues-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-issues/ + + + Maven Notifications List + notifications@maven.apache.org + notifications-subscribe@maven.apache.org + notifications-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-notifications/ + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + ASF + + PMC Chair + + -5 + + + brett + Brett Porter + brett@apache.org + ASF + + PMC Member + + +10 + + + evenisse + Emmanuel Venisse + evenisse@apache.org + ASF + + PMC Member + + +1 + + + kenney + Kenney Westerhof + kenney@apache.org + Neonics + + PMC Member + + +1 + + + snicoll + Stephane Nicoll + snicoll@apache.org + ASF + + PMC Member + + +1 + + + vmassol + Vincent Massol + vmassol@apache.org + ASF + + PMC Member + + +1 + + + fgiust + Fabrizio Giustina + fgiust@apache.org + openmind + + PMC Member + + +1 + + + epunzalan + Edwin Punzalan + epunzalan@mergere.com + Mergere + + Committer + + +8 + + + mperham + Mike Perham + mperham@gmail.com + IBM + + PMC Member + + -6 + + + jdcasey + John Casey + jdcasey@apache.org + ASF + + PMC Member + + -5 + + + trygvis + Trygve Laugstol + trygvis@apache.org + ASF + + PMC Member + + +1 + + + vsiveton + Vincent Siveton + vsiveton@apache.org + ASF + + PMC Member + + -5 + + + carlos + Carlos Sanchez + carlos@apache.org + ASF + + PMC Member + + +1 + + + dennisl + Dennis Lundberg + dennisl@apache.org + ASF + + PMC Member + + +1 + + + aheritier + Arnaud Heritier + aheritier@apache.org + ASF + + PMC Member + + +1 + + + handyande + Andrew Williams + handyande@apache.org + + Committer + + 0 + + + jtolentino + Ernesto Tolentino Jr. + jtolentino@apache.org + ASF + + PMC Member + + +8 + + + joakime + Joakim Erdfelt + joakime@apache.org + ASF + + PMC Member + + -5 + + + jmcconnell + Jesse McConnell + jmcconnell@apache.org + ASF + + PMC Member + + -6 + + + wsmoak + Wendy Smoak + wsmoak@apache.org + + Committer + + -7 + + + + + + + apache.website + scp://people.apache.org/www/maven.apache.org + + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.0-beta-4 + + + https://svn.apache.org/repos/asf/maven/pom/tags + false + deploy + -Prelease + + + + + + + + + ci + + + + org.apache.maven.plugins + maven-pmd-plugin + + + + cpd-check + + + + + + + + + reporting + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven_checks.xml + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven-header.txt + + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.codehaus.mojo + cobertura-maven-plugin + + + org.codehaus.mojo + taglist-maven-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + + + release + + + + + maven-gpg-plugin + 1.0-alpha-1 + + ${gpg.passphrase} + + + + + sign + + + + + + + true + maven-deploy-plugin + 2.3 + + ${deploy.altRepository} + true + + + + + maven-remote-resources-plugin + 1.0-alpha-1 + + + + process + + + + org.apache:apache-jar-resource-bundle:1.0 + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.0.2 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.2 + + + attach-javadocs + + jar + + + + + + + + + + + scm:svn:https://svn.apache.org/repos/asf/maven/pom/tags/maven-parent-5 + scm:svn:https://svn.apache.org/repos/asf/maven/pom/tags/maven-parent-5 + https://svn.apache.org/repos/asf/maven/pom/tags/maven-parent-5 + +
+ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 new file mode 100644 index 000000000000..27ba3aaf45d9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 @@ -0,0 +1 @@ +4da85635ce64dbec5b00232d5bb26453 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 new file mode 100644 index 000000000000..5d7a3eba5ad1 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 @@ -0,0 +1 @@ +5c1ab38decaca1ccd08294aeab135047ebbae00d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar new file mode 100644 index 000000000000..79fcf22652b3 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 new file mode 100644 index 000000000000..60aecbcd2f5e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 @@ -0,0 +1 @@ +f41eb4e07a725eea3332743a29057855 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 new file mode 100644 index 000000000000..e3f05109919a --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 @@ -0,0 +1 @@ +abd1c9ace6e87c94a4b91f5176aeb09d954b23a3 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom new file mode 100644 index 000000000000..dca027b28347 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom @@ -0,0 +1,21 @@ + + + wagon + org.apache.maven.wagon + 1.0-beta-2 + + 4.0.0 + wagon-provider-api + Maven Wagon API + 1.0-beta-2 + Maven Wagon API that defines the contract between different Wagon implementations + + + org.codehaus.plexus + plexus-utils + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..0f10b3fdc97d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +97f0a0bd0b81520ccccf8736b1fe380c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..56b9559d4b22 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +8b3013d0754edbeb694831ddf1c5d1a0019ee042 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom new file mode 100644 index 000000000000..768e3e958d72 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom @@ -0,0 +1,51 @@ + + + + wagon + org.apache.maven.wagon + 1.0-beta-2 + + 4.0.0 + wagon-providers + pom + Maven Wagon Providers Parent + + wagon-file + wagon-ftp + wagon-http-lightweight + wagon-http + wagon-http-shared + wagon-ssh-external + wagon-ssh-common + wagon-ssh-common-test + wagon-ssh + wagon-ssh-ganymed + wagon-webdav + + + + + org.apache.maven.wagon + wagon-ssh-common + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-ssh-common-test + 1.0-beta-2 + test + + + + + + org.apache.maven.wagon + wagon-provider-test + test + + + org.apache.maven.wagon + wagon-provider-api + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..45931fe876e3 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +5690a1f456b3360fe06aa4c81ceead2a \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..e7f68f27d701 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +a98eefeb315d771555c8529695630d3baefd1f6d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar new file mode 100644 index 000000000000..7ef31a349b10 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.md5 new file mode 100644 index 000000000000..2eaf8ef81fd4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.md5 @@ -0,0 +1 @@ +470c6e98201aa4c013cb467362208a6a \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.sha1 new file mode 100644 index 000000000000..7b03766dc69e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.sha1 @@ -0,0 +1 @@ +705d42d0d3bc584e1d01a892bb8bc01928c5b126 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom new file mode 100644 index 000000000000..e2b1fe654db0 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom @@ -0,0 +1,50 @@ + + + wagon-providers + org.apache.maven.wagon + 1.0-beta-2 + + 4.0.0 + wagon-webdav + Maven Wagon WebDav Provider + 1.0-beta-2 + Wagon that gets and puts artifacts through webdav protocol + + + Henry Isidro + hisidro@exist.com + + + Joakim Erdfelt + joakim@erdfelt.com + + + + + slide + slide-webdavlib + 2.1 + + + commons-logging + commons-logging + 1.0.4 + runtime + + + it.could + webdav + 0.4 + test + + + org.mortbay.jetty + jetty + 4.2.12 + test + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..7b1262e408bf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +fba1e35dd302eba826861b5be7351c4b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..39af910fccdf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +1f6d30fd6d75cba5b9ff3fb88cb35cf9f2895736 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom new file mode 100644 index 000000000000..ca84acc39de4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom @@ -0,0 +1,170 @@ + + + 4.0.0 + + maven-parent + org.apache.maven + 4 + ../pom/maven/pom.xml + + org.apache.maven.wagon + wagon + pom + Maven Wagon + 1.0-beta-2 + Tools to manage artifacts and deployment + http://maven.apache.org/wagon + + + jira + http://jira.codehaus.org/browse/WAGON + + 2003 + + + Maven Wagon User List + wagon-users-subscribe@maven.apache.org + wagon-users-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-wagon-users/ + + + Maven Wagon Developer List + wagon-dev-subscribe@maven.apache.org + wagon-dev-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-wagon-dev/ + + + Maven Commits List + wagon-commits-subscribe@maven.apache.org + wagon-commits-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-wagon-commits/ + + + + + michal + Michal Maczka + michal@codehaus.org + Codehaus + + Developer + + + + + scm:svn:https://svn.apache.org/repos/asf/maven/wagon/tags/wagon-1.0-beta-2 + scm:svn:https://svn.apache.org/repos/asf/maven/wagon/tags/wagon-1.0-beta-2 + https://svn.apache.org/repos/asf/maven/wagon/tags/wagon-1.0-beta-2 + + + + + + maven-release-plugin + + https://svn.apache.org/repos/asf/maven/wagon/tags + + + + + + + wagon-provider-api + wagon-provider-test + wagon-providers + + + + junit + junit + test + + + + + + org.apache.maven.wagon + wagon-provider-api + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-provider-test + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-ssh-common-test + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-ssh-common + 1.0-beta-2 + + + junit + junit + 4.13.1 + + + org.codehaus.plexus + plexus-interactivity-api + 1.0-alpha-4 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-8 + + + org.codehaus.plexus + plexus-utils + 1.0.4 + + + + + + + sharedResources + + + people.apache.org + http://people.apache.org/repo/m2-snapshot-repository + + true + + + + + + + org.apache.maven.plugins + maven-remote-resources-plugin + 1.0-alpha-1 + + + + process + + + + org.apache:apache-jar-resource-bundle:1.0 + + + + + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..45e066d7355f --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +e739bffedc84a18c6e10a0958e2006ad \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..5f82f766bd1e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +6cf8a47018be792d2b1774d2bacd7541c888ae50 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar new file mode 100644 index 000000000000..d3232758f2e1 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.md5 new file mode 100644 index 000000000000..1a9a2b6fbeca --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.md5 @@ -0,0 +1 @@ +1078ac2103fe666952a3cbcbff19ec71 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.sha1 new file mode 100644 index 000000000000..17dbef2e5a7d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.sha1 @@ -0,0 +1 @@ +c76ce4f9f1a3d04ef849c1d067519b77f07e01f3 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom new file mode 100644 index 000000000000..036543e364a7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom @@ -0,0 +1,51 @@ + + 4.0.0 + + plexus-components + org.codehaus.plexus + 1.1.6 + + + plexus-active-collections + 1.0-beta-1 + Plexus Container-Backed Active Collections + + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-16 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-16 + + + junit + junit + 4.13.1 + test + + + + + + + maven-surefire-plugin + + + **/TestComponent.java + **/TestBadComponent.java + **/*TCK.java + + + + + + + + scm:svn:https://svn.codehaus.org/plexus/tags/plexus-active-collections-1.0-beta-1 + scm:svn:https://svn.codehaus.org/plexus/tags/plexus-active-collections-1.0-beta-1 + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 new file mode 100644 index 000000000000..145191263a49 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 @@ -0,0 +1 @@ +d844f3e1934a76cefc25342bf02f3bff \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 new file mode 100644 index 000000000000..5442cbcd9ea7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 @@ -0,0 +1 @@ +cf6a9d40df4ca79c210b2b8a90ce28fffb202769 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar new file mode 100644 index 000000000000..e2143250f5ff Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.md5 new file mode 100644 index 000000000000..c7dfa1eaa0ce --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.md5 @@ -0,0 +1 @@ +f55402879506f435a386f2c002ed5001 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.sha1 new file mode 100644 index 000000000000..a333efb87665 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.sha1 @@ -0,0 +1 @@ +fc41205635dab152bf794785be80a0a70fda686e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom new file mode 100644 index 000000000000..62a4f45a6a5d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom @@ -0,0 +1,94 @@ + + + + + plexus + org.codehaus.plexus + 1.0.10 + + 4.0.0 + org.codehaus.plexus + plexus-classworlds + jar + Plexus Classworlds + 1.2-alpha-10 + + 2002 + + + junit + junit + 4.13.1 + jar + compile + + + + + + maven-surefire-plugin + + once + + + + maven-compiler-plugin + + + org/codehaus/plexus/classworlds/event/* + + + + + + + + debug + + + aspectj + aspectjrt + 1.5.0 + + + + + + org.codehaus.mojo + aspectj-maven-plugin + + + + compile + + + + + 1.4 + + + + + + + + scm:svn:http://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-10 + scm:svn:https://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-10 + http://fisheye.codehaus.org/browse/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-10 + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 new file mode 100644 index 000000000000..47dbce552644 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 @@ -0,0 +1 @@ +1a7177f5992983aeb393089af67e51dc \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 new file mode 100644 index 000000000000..eafd9a79fd49 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 @@ -0,0 +1 @@ +11215912b045533ec9aaba9f63ea27acf6da850e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar new file mode 100644 index 000000000000..a8f6a7d3ede8 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 new file mode 100644 index 000000000000..09c3bbade17e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 @@ -0,0 +1 @@ +b00a4521e82cd7cdf502039dd59a1ffb \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 new file mode 100644 index 000000000000..9a43138c2a1b --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 @@ -0,0 +1 @@ +ed03d1eeb9b2576747df0d2883d9006fa5e1febe \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom new file mode 100644 index 000000000000..d2fc895a2afb --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom @@ -0,0 +1,78 @@ + + + plexus + org.codehaus.plexus + 1.0.9 + + 4.0.0 + org.codehaus.plexus + plexus-classworlds + Plexus Classworlds + 1.2-alpha-7 + + 2002 + + scm:svn:http://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-7 + scm:svn:https://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-7 + http://fisheye.codehaus.org/browse/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-7 + + + + + maven-surefire-plugin + + once + + + + maven-compiler-plugin + + + org/codehaus/plexus/classworlds/event/* + + + + + + + + debug + + + + org.codehaus.mojo + aspectj-maven-plugin + + + + compile + + + + + 1.4 + + + + + + + aspectj + aspectjrt + 1.5.0 + + + + + + + junit + junit + 4.13.1 + compile + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 new file mode 100644 index 000000000000..e9083e7996e5 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 @@ -0,0 +1 @@ +80962d09b250824806ca66b0bd0ad4c1 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 new file mode 100644 index 000000000000..4b9e8a40b640 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 @@ -0,0 +1 @@ +6944ec0d0cab19adf167332f7197e045d64a577c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar new file mode 100644 index 000000000000..85669fdd858e Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 new file mode 100644 index 000000000000..1830fc9e9b3a --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 @@ -0,0 +1 @@ +4fe3c03b97ff12905d0fb10fc5b36766 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 new file mode 100644 index 000000000000..7456120dbd0e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 @@ -0,0 +1 @@ +5a2100a1c6a37804b1abfc70000b0ea33b83b7f9 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom new file mode 100644 index 000000000000..b151164086c2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom @@ -0,0 +1,63 @@ + + + plexus-containers + org.codehaus.plexus + 1.0-alpha-16 + + 4.0.0 + plexus-component-api + Plexus Component API + 1.0-alpha-16 + + + + maven-surefire-plugin + 2.2 + + + **/Test*.java + **/Abstract*.java + + + + + + + + org.codehaus.plexus + plexus-classworlds + + + + + + maven-surefire-report-plugin + + + maven-pmd-plugin + + + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 new file mode 100644 index 000000000000..78fc8ace6433 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 @@ -0,0 +1 @@ +751ea77f1e617aea90f36d7156762bf5 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 new file mode 100644 index 000000000000..dea608840f98 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 @@ -0,0 +1 @@ +53ad54acd9589c497ba54740f0455fec55db64d7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar new file mode 100644 index 000000000000..5e3a919c470c Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 new file mode 100644 index 000000000000..beb51a4fb8e8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 @@ -0,0 +1 @@ +7146edcc3412c2b54df27edaf66b00a6 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 new file mode 100644 index 000000000000..4a7df6b7be56 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 @@ -0,0 +1 @@ +b226de4eb8db939dff4e14eb5aa1be045c39f6f4 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom new file mode 100644 index 000000000000..f6ff7ea05681 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom @@ -0,0 +1,61 @@ + + 4.0.0 + + org.codehaus.plexus + plexus-containers + 1.0-alpha-32 + + plexus-component-api + Plexus Component API + 1.0-alpha-32 + + + + maven-surefire-plugin + 2.2 + + + **/Test*.java + **/Abstract*.java + + + + + + + + org.codehaus.plexus + plexus-classworlds + + + + + + + maven-surefire-report-plugin + + + maven-pmd-plugin + + + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 new file mode 100644 index 000000000000..40890b2c332f --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 @@ -0,0 +1 @@ +a181ee89516009cff7658eec175ccb23 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 new file mode 100644 index 000000000000..f854c7a1436b --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 @@ -0,0 +1 @@ +e214782e714b87b38d5605cb8da53b7d98efde06 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom new file mode 100644 index 000000000000..2adef07e6e46 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom @@ -0,0 +1,60 @@ + + + + 4.0.0 + + plexus + org.codehaus.plexus + 1.0.8 + + org.codehaus.plexus + plexus-components + pom + 1.1.6 + Plexus Components Parent Project + + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-8 + + + + plexus-action + plexus-archiver + plexus-bayesian + plexus-command + plexus-compiler + plexus-drools + plexus-formica + plexus-formica-web + plexus-hibernate + plexus-i18n + plexus-interactivity + plexus-ircbot + plexus-jdo + plexus-jetty-httpd + plexus-jetty + plexus-mimetyper + plexus-notification + plexus-resource + plexus-security + plexus-summit + plexus-taskqueue + plexus-velocity + plexus-xmlrpc + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 new file mode 100644 index 000000000000..cf57067b0dd8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 @@ -0,0 +1 @@ +b76cb94eb4ade475f4743d3656c40899 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 new file mode 100644 index 000000000000..b9f0aa795324 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 @@ -0,0 +1 @@ +682713aa402653d0ea5e224870dc899803734519 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar new file mode 100644 index 000000000000..ef2bd9072a34 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 new file mode 100644 index 000000000000..fc1ee0b6f3c6 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 @@ -0,0 +1 @@ +00b4ce443fa584a1998cd6f991ea6514 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 new file mode 100644 index 000000000000..879c8890a4f7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 @@ -0,0 +1 @@ +dcad8d44306c5ecc109b9449f292fb28b75d37ef \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom new file mode 100644 index 000000000000..f5ae54892c72 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom @@ -0,0 +1,56 @@ + + + plexus-containers + org.codehaus.plexus + 1.0-alpha-16 + + 4.0.0 + plexus-container-default + Default Plexus Container + 1.0-alpha-16 + + + + maven-surefire-plugin + + once + + **/Test*.java + **/Abstract*.java + + + + + maven-assembly-plugin + + + jar-with-dependencies + + + + + + + + org.codehaus.plexus + plexus-component-api + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-classworlds + + + jmock + jmock + 1.0.1 + test + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 new file mode 100644 index 000000000000..611807a8bdd4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 @@ -0,0 +1 @@ +883b6e1e40cccb06c1d1ce93728b0a9d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 new file mode 100644 index 000000000000..ea4d6dc0032d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 @@ -0,0 +1 @@ +435f5d09ea241e93acaecd4b6680ddb13a36837d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar new file mode 100644 index 000000000000..308893f62473 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 new file mode 100644 index 000000000000..291ffea0e4fc --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 @@ -0,0 +1 @@ +556231599b5413a7c1f16a5fd15be574 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 new file mode 100644 index 000000000000..b8ef047d7dc3 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 @@ -0,0 +1 @@ +91410b971f9659f76b0ff26a97b9fbac5de2f69e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom new file mode 100644 index 000000000000..f8b070541514 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom @@ -0,0 +1,98 @@ + + 4.0.0 + + org.codehaus.plexus + plexus-containers + 1.0-alpha-32 + + plexus-container-default + Default Plexus Container + 1.0-alpha-32 + + + + maven-surefire-plugin + + once + + **/Test*.java + **/Abstract*.java + + + + + shade-maven-plugin + org.codehaus.mojo + 1.0-alpha-9 + + + package + + shade + + + + + classworlds:classworlds + junit:junit + jmock:jmock + org.codehaus.plexus:plexus-classworlds + org.codehaus.plexus:plexus-utils + + + + + + + + + + + org.codehaus.plexus + plexus-component-api + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-classworlds + + + jmock + jmock + 1.0.1 + test + + + + + + + maven-pmd-plugin + + + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 new file mode 100644 index 000000000000..3b237719bf5d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 @@ -0,0 +1 @@ +af4ca0022b674405556b3f397e375adc \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 new file mode 100644 index 000000000000..00b60872ed19 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 @@ -0,0 +1 @@ +8f4d09d36a2345a39301dbd77ef9906c795887f7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom new file mode 100644 index 000000000000..1e8675857945 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom @@ -0,0 +1,49 @@ + + 4.0.0 + + org.codehaus.plexus + plexus + 1.0.9 + + org.codehaus.plexus + plexus-containers + pom + Parent Plexus Container POM + 1.0-alpha-16 + + plexus-component-api + plexus-container-default + + + scm:svn:http://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-16 + scm:svn:https://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-16 + http://fisheye.codehaus.org/browse/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-16 + + + + junit + junit + + compile + + + + + + org.codehaus.plexus + plexus-classworlds + 1.2-alpha-7 + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-16 + + + org.codehaus.plexus + plexus-utils + 1.3 + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 new file mode 100644 index 000000000000..3db22e20eb81 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 @@ -0,0 +1 @@ +3eee2016e3e307618048e30f088b546e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 new file mode 100644 index 000000000000..3eb3627146ee --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 @@ -0,0 +1 @@ +46b79dd7d6a8130d2fa81c80b16b695d491548fe \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom new file mode 100644 index 000000000000..8e94894a4272 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom @@ -0,0 +1,49 @@ + + 4.0.0 + + org.codehaus.plexus + plexus + 1.0.11 + + org.codehaus.plexus + plexus-containers + pom + Parent Plexus Container POM + 1.0-alpha-32 + + plexus-component-api + plexus-container-default + + + scm:svn:http://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-32 + scm:svn:https://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-32 + http://fisheye.codehaus.org/browse/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-32 + + + + junit + junit + 4.13.1 + compile + + + + + + org.codehaus.plexus + plexus-classworlds + 1.2-alpha-10 + + + org.codehaus.plexus + plexus-utils + 1.4.5 + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-32 + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 new file mode 100644 index 000000000000..41815f084a76 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 @@ -0,0 +1 @@ +8ac33e07134648d37e2b1253286889a7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 new file mode 100644 index 000000000000..4126071626cf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 @@ -0,0 +1 @@ +8486ff9b37d1ade2a4524c6fee72d394f88fbe08 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar new file mode 100644 index 000000000000..a2013d470581 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 new file mode 100644 index 000000000000..686c680774ce --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 @@ -0,0 +1 @@ +60783e4623f2e44063cf2d43d9fbacb2816855c2 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom new file mode 100644 index 000000000000..4c608288267d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom @@ -0,0 +1,235 @@ + + 4.0.0 + org.codehaus.plexus + plexus-utils + Plexus Common Utilities + 1.0.4 + + + + +
dev@plexus.codehaus.org
+
+
+ + irc + + 6667 + #plexus + irc.codehaus.org + + +
+
+ 2001 + + + Plexus Developer List + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/pipermail/plexus-dev/ + + + + + jvanzyl + Jason van Zyl + jason@zenplex.com + Zenplex + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + trygvis + Trygve Laugstol + trygvis@codehaus.org + + Developer + + + + kenney + Kenney Westerhof + kenney@codehaus.org + + Developer + + + + + scm:svn:svn://svn.codehaus.org/plexus/scm/trunk/plexus-utils + scm:svn:https://svn.codehaus.org/plexus/trunk/plexus-utils + + + Codehaus + http://www.codehaus.org/ + + + src/main/java + src/main/scripts + src/test/java + target/classes + target/test-classes + + + src/main/resources + + + + + src/test/resources + + + target + + + maven-release-plugin + 2.0-beta-3-SNAPSHOT + + https://svn.codehaus.org/plexus/tags + + + + maven-surefire-plugin + RELEASE + + + org/codehaus/plexus/util/FileBasedTestCase.java + **/Test*.java + + + + + + + + + false + + snapshots + Maven Snapshot Development Repository + http://snapshots.maven.codehaus.org/maven2 + + + + false + + central + Maven Repository Switchboard + http://repo1.maven.org/maven2 + + + + + + false + + snapshots-plugins + Maven Snapshot Plugins Development Repository + http://snapshots.maven.codehaus.org/maven2 + + + + false + + central + Maven Plugin Repository + http://repo1.maven.org/maven2 + + + + + junit + junit + 3.8.1 + test + + + + target/site + + + + repo1 + Maven Central Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/to-ibiblio/maven2 + + + snapshots + Maven Central Development Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/snapshots/maven2 + + deployed + +
\ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 new file mode 100644 index 000000000000..f74d077845a5 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 @@ -0,0 +1 @@ +a82e1ddd2d795616ac58d73ed246b8ec65326dfa /home/projects/maven/repository-staging/to-ibiblio/maven2/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar new file mode 100644 index 000000000000..5c50e1779f7e Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 new file mode 100644 index 000000000000..a7ca769a03a0 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 @@ -0,0 +1 @@ +49e112a6c1ad24962643ef9494f9cbe1 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 new file mode 100644 index 000000000000..28f6dbb585ab --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 @@ -0,0 +1 @@ +fa632b7f1cb7c50963d0fb7d818ca93c75c10127 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom new file mode 100644 index 000000000000..6cf9079989bf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom @@ -0,0 +1,27 @@ + + + plexus + org.codehaus.plexus + 1.0.4 + + 4.0.0 + plexus-utils + Plexus Common Utilities + 1.1 + + + + maven-surefire-plugin + + + org/codehaus/plexus/util/FileBasedTestCase.java + **/Test*.java + + + + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 new file mode 100644 index 000000000000..6de9bf4794f2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 @@ -0,0 +1 @@ +6e902bab552ae52fef5875d27c4cf0a0 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 new file mode 100644 index 000000000000..4dc64d4ae8c9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 @@ -0,0 +1 @@ +15492ecd00920daca9ec15f6acd695b626621e5b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar new file mode 100644 index 000000000000..449afb9c1fe3 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 new file mode 100644 index 000000000000..eff56f281fbd --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 @@ -0,0 +1 @@ +e158df8d1a539cc6482567f9689cc36f \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 new file mode 100644 index 000000000000..953f76d88838 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 @@ -0,0 +1 @@ +56559396674aacd498c298964b691db0177027c0 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom new file mode 100644 index 000000000000..55baddfd90f2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom @@ -0,0 +1,61 @@ + + + plexus + org.codehaus.plexus + 1.0.11 + ../pom/pom.xml + + 4.0.0 + plexus-utils + Plexus Common Utilities + 1.4.5 + http://plexus.codehaus.org/plexus-utils + + + + maven-compiler-plugin + + + 1.3 + 1.3 + + + + maven-surefire-plugin + + + true + + org/codehaus/plexus/util/FileBasedTestCase.java + **/Test*.java + + + + JAVA_HOME + ${JAVA_HOME} + + + M2_HOME + ${M2_HOME} + + + + + + + + scm:svn:http://svn.codehaus.org/plexus/plexus-utils/tags/plexus-utils-1.4.5 + scm:svn:https://svn.codehaus.org/plexus/plexus-utils/tags/plexus-utils-1.4.5 + http://fisheye.codehaus.org/browse/plexus/plexus-utils/tags/plexus-utils-1.4.5 + + + + + maven-javadoc-plugin + + + maven-jxr-plugin + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 new file mode 100644 index 000000000000..905f70a9b275 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 @@ -0,0 +1 @@ +fccab705018ed5559df9f8e815b79aaa \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 new file mode 100644 index 000000000000..247cd9435608 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 @@ -0,0 +1 @@ +0bdc8a7fbce7d9007a93d289a029b43e1196d85c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom new file mode 100644 index 000000000000..ee904a03dfcc --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom @@ -0,0 +1,273 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.10 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus User List + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://archive.plexus.codehaus.org/user + + + Plexus Developer List + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://archive.plexus.codehaus.org/dev + + + Plexus Announce List + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://archive.plexus.codehaus.org/announce + + + Plexus Commit List + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://archive.plexus.codehaus.org/scm + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + codehaus.snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + Andrew Williams + handyande + andy@handyande.co.uk + + Developer + + + + Rahul Thakur + rahul + rahul.thakur.xdev@gmail.com + + Developer + + + + Joakim Erdfelt + joakime + joakim@erdfelt.com + + Developer + + + + Olivier Lamy + olamy + olamy@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/pom/tags/plexus-1.0.10 + scm:svn:https://svn.codehaus.org/plexus/pom/tags/plexus-1.0.10 + http://fisheye.codehaus.org/browse/plexus/pom/tags/plexus-1.0.10 + + + Codehaus + http://www.codehaus.org/ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-2 + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 new file mode 100644 index 000000000000..7ae43d7e91ab --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 @@ -0,0 +1 @@ +6ab958c91424c0d7c3a2cc861867905e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 new file mode 100644 index 000000000000..8ed366f9891d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 @@ -0,0 +1 @@ +039c3f6a3cbe1f9e7b4a3309d9d7062b6e390fa7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom new file mode 100644 index 000000000000..1f491ae4f742 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom @@ -0,0 +1,308 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.11 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + Plexus User List + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://archive.plexus.codehaus.org/user + + + Plexus Developer List + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://archive.plexus.codehaus.org/dev + + + Plexus Announce List + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://archive.plexus.codehaus.org/announce + + + Plexus Commit List + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://archive.plexus.codehaus.org/scm + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + codehaus.snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + Andrew Williams + handyande + andy@handyande.co.uk + + Developer + + + + Rahul Thakur + rahul + rahul.thakur.xdev@gmail.com + + Developer + + + + Joakim Erdfelt + joakime + joakim@erdfelt.com + + Developer + + + + Olivier Lamy + olamy + olamy@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/pom/trunk/ + scm:svn:https://svn.codehaus.org/plexus/pom/trunk/ + http://fisheye.codehaus.org/browse/plexus/pom/trunk/ + + + Codehaus + http://www.codehaus.org/ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-2 + + + + + + maven-release-plugin + + deploy + + + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 new file mode 100644 index 000000000000..2cabbba02bdc --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 @@ -0,0 +1 @@ +bdf8dcfe0877af604f7e19e9ffdf260b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 new file mode 100644 index 000000000000..1ba2b3afc2ee --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 @@ -0,0 +1 @@ +4693d4512d50c5159bef1c49def1d2690a327c30 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom new file mode 100644 index 000000000000..0867e8bc0eee --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom @@ -0,0 +1,205 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.4 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus Developer List + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/pipermail/plexus-dev/ + + + + + + repo1 + Maven Central Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/to-ibiblio/maven2 + + + snapshots + Maven Central Development Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/snapshots/maven2 + + + + + snapshots + Maven Snapshot Development Repository + http://snapshots.maven.codehaus.org/maven2 + + false + + + + + + snapshots-plugins + Maven Snapshot Plugins Development Repository + http://snapshots.maven.codehaus.org/maven2 + + false + + + + + + + jvanzyl + Jason van Zyl + jason@zenplex.com + Zenplex + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstøl + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:svn://svn.codehaus.org/plexus/scm/trunk/ + scm:svn:https://svn.codehaus.org/plexus/trunk + + + Codehaus + http://www.codehaus.org/ + + + plexus-appserver + plexus-archetypes + plexus-components + plexus-component-factories + plexus-containers + plexus-logging + plexus-maven-plugin + plexus-services + plexus-tools + plexus-utils + + + + + org.apache.maven.plugins + maven-release-plugin + + https://svn.codehaus.org/plexus/tags + + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 new file mode 100644 index 000000000000..ec5562d8b81d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 @@ -0,0 +1 @@ +2e97f3a7666e337ce5d2d98b9c384cae \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 new file mode 100644 index 000000000000..456d534766a4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 @@ -0,0 +1 @@ +06f66b2f7d2eef1d805c11bca91c89984cda4137 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom new file mode 100644 index 000000000000..c6afe11423ef --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom @@ -0,0 +1,259 @@ + + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.8 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus Developer List + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/pipermail/plexus-dev/ + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + apache-snapshots + Snapshot repository + http://people.apache.org/maven-snapshot-repository + + false + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/trunk/ + scm:svn:https://svn.codehaus.org/plexus/trunk + + + Codehaus + http://www.codehaus.org/ + + + + plexus-archetypes + plexus-examples + plexus-components + plexus-component-factories + plexus-containers + plexus-logging + plexus-maven-plugin + plexus-tools + plexus-utils + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-1 + + + + + org.apache.maven.plugins + maven-release-plugin + + https://svn.codehaus.org/plexus/tags + + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 new file mode 100644 index 000000000000..e0d40fcdad43 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 @@ -0,0 +1 @@ +2da4039a1c4c959c75d3e6126f2029cf \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 new file mode 100644 index 000000000000..5234d5638aaf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 @@ -0,0 +1 @@ +9e7c8432829962afe796b32587c1bfa841a317d5 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom new file mode 100644 index 000000000000..6f4e50097db1 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom @@ -0,0 +1,257 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.9 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus User List + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://archive.plexus.codehaus.org/user + + + Plexus Developer List + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://archive.plexus.codehaus.org/dev + + + Plexus Announce List + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://archive.plexus.codehaus.org/announce + + + Plexus Commit List + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://archive.plexus.codehaus.org/scm + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + apache-snapshots + Snapshot repository + http://people.apache.org/maven-snapshot-repository + + false + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + Andrew Williams + handyande + andy@handyande.co.uk + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/pom/tags/plexus-1.0.9 + scm:svn:https://svn.codehaus.org/plexus/pom/tags/plexus-1.0.9 + http://fisheye.codehaus.org/browse/plexus/pom/tags/plexus-1.0.9 + + + Codehaus + http://www.codehaus.org/ + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-1 + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 new file mode 100644 index 000000000000..3910bf8b1725 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 @@ -0,0 +1 @@ +acf338e422e5c0d9c6242e4f21e63dc9 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 new file mode 100644 index 000000000000..df40a701c140 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 @@ -0,0 +1 @@ +89d241b1e5ee6a72d3dd95d9eb90f635deebcdb2 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated new file mode 100644 index 000000000000..d326d8b4f020 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Wed Jan 05 14:06:51 CET 2022 +https\://repo.maven.apache.org/maven2/.lastUpdated=1641388011987 +https\://repo.maven.apache.org/maven2/.error= diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar new file mode 100644 index 000000000000..eb935e035fa5 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 new file mode 100644 index 000000000000..304c4b0f90b2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 @@ -0,0 +1 @@ +ad09811315f1d4f5756986575b0ea16b99cd686f \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar new file mode 100644 index 000000000000..c3c110b4dab6 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 new file mode 100644 index 000000000000..ce64bf95e5c8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 @@ -0,0 +1 @@ +1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar new file mode 100644 index 000000000000..9d5fe16e3dd3 Binary files /dev/null and b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar differ diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 new file mode 100644 index 000000000000..1085ece454c9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 @@ -0,0 +1 @@ +42a25dc3219429f0e5d060061f71acb49bf010a0 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom new file mode 100644 index 000000000000..0721781c99a0 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom @@ -0,0 +1,18 @@ + + + 4.0.0 + + + org.hamcrest + hamcrest-parent + 1.3 + + + hamcrest-core + jar + Hamcrest Core + + This is the core API of hamcrest matcher framework to be used by third-party framework providers. This includes the a foundation set of matcher implementations for common operations. + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 new file mode 100644 index 000000000000..53d5f15b56c5 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 @@ -0,0 +1 @@ +872e413497b906e7c9fa85ccc96046c5d1ef7ece \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom new file mode 100644 index 000000000000..ae4b4b4df8dd --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom @@ -0,0 +1,72 @@ + + + 4.0.0 + + org.hamcrest + hamcrest-parent + 1.3 + pom + + Hamcrest Maven Parent + https://github.com/hamcrest/JavaHamcrest + General parent POM for all hamcrest libraries. + + + + New BSD License + http://www.opensource.org/licenses/bsd-license.php + repo + + + + + https://github.com/hamcrest/JavaHamcrest + scm:git:git@github.com:hamcrest/JavaHamcrest.git + + + + + joe.walnes + Joe Walnes + + Developer + + + + nat.pryce + Nat Pryce + + Developer + + + + smgfreeman + Steve Freeman + + Developer + + + + neildunn + Neil Dunn + + Developer + + + + scarytom + Tom Denley + + Developer + + + + + + hamcrest-core + hamcrest-generator + hamcrest-library + hamcrest-integration + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 new file mode 100644 index 000000000000..c5c5f185ebd8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 @@ -0,0 +1 @@ +80391bd32bfa4837a15215d5e9f07c60555c379a \ No newline at end of file diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index 598dcaa04ee7..10cca57da712 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -73,6 +73,7 @@ import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest; import org.apache.maven.toolchain.building.ToolchainsBuilder; import org.apache.maven.toolchain.building.ToolchainsBuildingResult; +import org.apache.maven.toolchain.model.PersistedToolchains; import org.codehaus.plexus.ContainerConfiguration; import org.codehaus.plexus.DefaultContainerConfiguration; import org.codehaus.plexus.DefaultPlexusContainer; @@ -1334,7 +1335,7 @@ void toolchains( CliRequest cliRequest ) eventSpyDispatcher.onEvent( toolchainsResult ); executionRequestPopulator.populateFromToolchains( cliRequest.request, - toolchainsResult.getEffectiveToolchains() ); + new PersistedToolchains( toolchainsResult.getEffectiveToolchains() ) ); if ( !toolchainsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled() ) { diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java index ef0c55360c08..5bdc8895b41a 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java @@ -35,11 +35,11 @@ import org.apache.maven.cli.CliRequest; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequestPopulationException; -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Repository; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Mirror; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.Server; +import org.apache.maven.api.settings.Settings; import org.apache.maven.settings.SettingsUtils; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuilder; @@ -188,9 +188,7 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques for ( Server server : settings.getServers() ) { - server = server.clone(); - - request.addServer( server ); + request.addServer( new org.apache.maven.settings.Server( server ) ); } // @@ -212,9 +210,7 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques continue; } - proxy = proxy.clone(); - - request.addProxy( proxy ); + request.addProxy( new org.apache.maven.settings.Proxy( proxy ) ); } // @@ -227,14 +223,12 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques for ( Mirror mirror : settings.getMirrors() ) { - mirror = mirror.clone(); - - request.addMirror( mirror ); + request.addMirror( new org.apache.maven.settings.Mirror( mirror ) ); } request.setActiveProfiles( settings.getActiveProfiles() ); - for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) + for ( org.apache.maven.api.settings.Profile rawProfile : settings.getProfiles() ) { request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile ) ); @@ -245,8 +239,8 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques { try { - request.addRemoteRepository( - MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); + request.addRemoteRepository( MavenRepositorySystem.buildArtifactRepository( + new org.apache.maven.settings.Repository( remoteRepository ) ) ); } catch ( InvalidRepositoryException e ) { @@ -259,8 +253,8 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques { try { - request.addPluginArtifactRepository( - MavenRepositorySystem.buildArtifactRepository( pluginRepository ) ); + request.addPluginArtifactRepository( MavenRepositorySystem.buildArtifactRepository( + new org.apache.maven.settings.Repository( pluginRepository ) ) ); } catch ( InvalidRepositoryException e ) { diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java index f3583e224d35..df5638001eca 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java @@ -34,7 +34,7 @@ import org.apache.maven.extension.internal.CoreExports; import org.apache.maven.extension.internal.CoreExtensionEntry; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Plugin; import org.apache.maven.plugin.PluginResolutionException; import org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver; import org.codehaus.plexus.DefaultPlexusContainer; @@ -181,13 +181,15 @@ private List resolveExtension( CoreExtension extension, RepositorySyst * resolveCoreExtension method which uses a CoreExtension * object instead of a Plugin as this makes no sense. */ - Plugin plugin = new Plugin(); - plugin.setGroupId( interpolator.interpolate( extension.getGroupId() ) ); - plugin.setArtifactId( interpolator.interpolate( extension.getArtifactId() ) ); - plugin.setVersion( interpolator.interpolate( extension.getVersion() ) ); + Plugin plugin = Plugin.newBuilder() + .groupId( interpolator.interpolate( extension.getGroupId() ) ) + .artifactId( interpolator.interpolate( extension.getArtifactId() ) ) + .version( interpolator.interpolate( extension.getVersion() ) ) + .build(); DependencyNode root = pluginDependenciesResolver - .resolveCoreExtension( plugin, dependencyFilter, repositories, repoSession ); + .resolveCoreExtension( new org.apache.maven.model.Plugin( plugin ), + dependencyFilter, repositories, repoSession ); PreorderNodeListGenerator nlg = new PreorderNodeListGenerator(); root.accept( nlg ); diff --git a/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java b/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java new file mode 100644 index 000000000000..e10551ae93bc --- /dev/null +++ b/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java @@ -0,0 +1,486 @@ +package org.eclipse.sisu.plexus; + +/* + * 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. + */ + +import javax.annotation.Priority; +import javax.inject.Inject; +import javax.inject.Singleton; + +import java.io.StringReader; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; +import com.google.inject.spi.TypeConverter; +import com.google.inject.spi.TypeConverterBinding; +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.eclipse.sisu.bean.BeanProperties; +import org.eclipse.sisu.bean.BeanProperty; +import org.eclipse.sisu.inject.Logs; +import org.eclipse.sisu.inject.TypeArguments; + +/** + * {@link PlexusBeanConverter} {@link Module} that converts Plexus XML configuration into beans. + */ +@Singleton +@Priority( 10 ) +public final class PlexusXmlBeanConverter + implements PlexusBeanConverter +{ + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + private static final String CONVERSION_ERROR = "Cannot convert: \"%s\" to: %s"; + + // ---------------------------------------------------------------------- + // Implementation fields + // ---------------------------------------------------------------------- + + private final Collection typeConverterBindings; + + // ---------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------- + + @Inject + PlexusXmlBeanConverter( final Injector injector ) + { + typeConverterBindings = injector.getTypeConverterBindings(); + } + + // ---------------------------------------------------------------------- + // Public methods + // ---------------------------------------------------------------------- + + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public Object convert( final TypeLiteral role, final String value ) + { + if ( value.trim().startsWith( "<" ) ) + { + try + { + final MXParser parser = new MXParser(); + parser.setInput( new StringReader( value ) ); + parser.nextTag(); + + return parse( parser, role ); + } + catch ( final Exception e ) + { + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, role ), e ); + } + } + + return convertText( value, role ); + } + + // ---------------------------------------------------------------------- + // Implementation methods + // ---------------------------------------------------------------------- + + /** + * Parses a sequence of XML elements and converts them to the given target type. + * + * @param parser The XML parser + * @param toType The target type + * @return Converted instance of the target type + */ + private Object parse( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + parser.require( XmlPullParser.START_TAG, null, null ); + + final Class rawType = toType.getRawType(); + if ( Dom.class.isAssignableFrom( rawType ) ) + { + return org.apache.maven.internal.xml.Xpp3DomBuilder.build( parser ); + } + if ( Xpp3Dom.class.isAssignableFrom( rawType ) ) + { + return parseXpp3Dom( parser ); + } + if ( Properties.class.isAssignableFrom( rawType ) ) + { + return parseProperties( parser ); + } + if ( Map.class.isAssignableFrom( rawType ) ) + { + return parseMap( parser, TypeArguments.get( toType.getSupertype( Map.class ), 1 ) ); + } + if ( Collection.class.isAssignableFrom( rawType ) ) + { + return parseCollection( parser, TypeArguments.get( toType.getSupertype( Collection.class ), 0 ) ); + } + if ( rawType.isArray() ) + { + return parseArray( parser, TypeArguments.get( toType, 0 ) ); + } + return parseBean( parser, toType, rawType ); + } + + /** + * Parses an XML subtree and converts it to the {@link Xpp3Dom} type. + * + * @param parser The XML parser + * @return Converted Xpp3Dom instance + */ + private static Xpp3Dom parseXpp3Dom( final XmlPullParser parser ) + throws Exception + { + return Xpp3DomBuilder.build( parser ); + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Properties} type. + * + * @param parser The XML parser + * @return Converted Properties instance + */ + private static Properties parseProperties( final XmlPullParser parser ) + throws Exception + { + final Properties properties = newImplementation( parser, Properties.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + parser.nextTag(); + // 'name-then-value' or 'value-then-name' + if ( "name".equals( parser.getName() ) ) + { + final String name = parser.nextText(); + parser.nextTag(); + properties.put( name, parser.nextText() ); + } + else + { + final String value = parser.nextText(); + parser.nextTag(); + properties.put( parser.nextText(), value ); + } + parser.nextTag(); + } + return properties; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Map} type. + * + * @param parser The XML parser + * @return Converted Map instance + */ + private Map parseMap( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + @SuppressWarnings( "unchecked" ) + final Map map = newImplementation( parser, HashMap.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + map.put( parser.getName(), parse( parser, toType ) ); + } + return map; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Collection} type. + * + * @param parser The XML parser + * @return Converted Collection instance + */ + private Collection parseCollection( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + @SuppressWarnings( "unchecked" ) + final Collection collection = newImplementation( parser, ArrayList.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + collection.add( parse( parser, toType ) ); + } + return collection; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate array type. + * + * @param parser The XML parser + * @return Converted array instance + */ + private Object parseArray( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + // convert to a collection first then convert that into an array + final Collection collection = parseCollection( parser, toType ); + final Object array = Array.newInstance( toType.getRawType(), collection.size() ); + + int i = 0; + for ( final Object element : collection ) + { + Array.set( array, i++, element ); + } + + return array; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate bean type. + * + * @param parser The XML parser + * @return Converted bean instance + */ + private Object parseBean( final MXParser parser, final TypeLiteral toType, final Class rawType ) + throws Exception + { + final Class clazz = loadImplementation( parseImplementation( parser ), rawType ); + + // simple bean? assumes string constructor + if ( parser.next() == XmlPullParser.TEXT ) + { + final String text = parser.getText(); + + // confirm element doesn't contain nested XML + if ( parser.next() != XmlPullParser.START_TAG ) + { + return convertText( text, clazz == rawType ? toType : TypeLiteral.get( clazz ) ); + } + } + + if ( String.class == clazz ) + { + // mimic plexus: discard any strings containing nested XML + while ( parser.getEventType() == XmlPullParser.START_TAG ) + { + final String pos = parser.getPositionDescription(); + Logs.warn( "Expected TEXT, not XML: {}", pos, new Throwable() ); + parser.skipSubTree(); + parser.nextTag(); + } + return ""; + } + + final Object bean = newImplementation( clazz ); + + // build map of all known bean properties belonging to the chosen implementation + final Map> propertyMap = new HashMap>(); + for ( final BeanProperty property : new BeanProperties( clazz ) ) + { + final String name = property.getName(); + if ( !propertyMap.containsKey( name ) ) + { + propertyMap.put( name, property ); + } + } + + while ( parser.getEventType() == XmlPullParser.START_TAG ) + { + // update properties inside the bean, guided by the cached property map + final BeanProperty property = propertyMap.get( Roles.camelizeName( parser.getName() ) ); + if ( property != null ) + { + property.set( bean, parse( parser, property.getType() ) ); + parser.nextTag(); + } + else + { + throw new XmlPullParserException( "Unknown bean property: " + parser.getName(), parser, null ); + } + } + + return bean; + } + + /** + * Parses an XML element looking for the name of a custom implementation. + * + * @param parser The XML parser + * @return Name of the custom implementation; otherwise {@code null} + */ + private static String parseImplementation( final XmlPullParser parser ) + { + return parser.getAttributeValue( null, "implementation" ); + } + + /** + * Attempts to load the named implementation, uses default implementation if no name is given. + * + * @param name The optional implementation name + * @param defaultClazz The default implementation type + * @return Custom implementation type if one was given; otherwise default implementation type + */ + private static Class loadImplementation( final String name, final Class defaultClazz ) + { + if ( null == name ) + { + return defaultClazz; // just use the default type + } + + // TCCL allows surrounding container to influence class loading policy + final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + if ( tccl != null ) + { + try + { + return tccl.loadClass( name ); + } + catch ( final Exception e ) + { + // drop through... + } + catch ( final LinkageError e ) + { + // drop through... + } + } + + // assume custom type is in same class space as default + final ClassLoader peer = defaultClazz.getClassLoader(); + if ( peer != null ) + { + try + { + return peer.loadClass( name ); + } + catch ( final Exception e ) + { + // drop through... + } + catch ( final LinkageError e ) + { + // drop through... + } + } + + try + { + // last chance - classic model + return Class.forName( name ); + } + catch ( final Exception e ) + { + throw new TypeNotPresentException( name, e ); + } + catch ( final LinkageError e ) + { + throw new TypeNotPresentException( name, e ); + } + } + + /** + * Creates an instance of the given implementation using the default constructor. + * + * @param clazz The implementation type + * @return Instance of given implementation + */ + private static T newImplementation( final Class clazz ) + { + try + { + return clazz.newInstance(); + } + catch ( final Exception e ) + { + throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); + } + catch ( final LinkageError e ) + { + throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); + } + } + + /** + * Creates an instance of the given implementation using the given string, assumes a public string constructor. + * + * @param clazz The implementation type + * @param value The string argument + * @return Instance of given implementation, constructed using the the given string + */ + private static T newImplementation( final Class clazz, final String value ) + { + try + { + return clazz.getConstructor( String.class ).newInstance( value ); + } + catch ( final Exception e ) + { + final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), cause ); + } + catch ( final LinkageError e ) + { + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), e ); + } + } + + /** + * Creates an instance of the implementation named in the current XML element, or the default if no name is given. + * + * @param parser The XML parser + * @param defaultClazz The default implementation type + * @return Instance of custom implementation if one was given; otherwise instance of default type + */ + @SuppressWarnings( "unchecked" ) + private static T newImplementation( final XmlPullParser parser, final Class defaultClazz ) + { + return (T) newImplementation( loadImplementation( parseImplementation( parser ), defaultClazz ) ); + } + + /** + * Converts the given string to the target type, using {@link TypeConverter}s registered with the {@link Injector}. + * + * @param value The string value + * @param toType The target type + * @return Converted instance of the target type + */ + private Object convertText( final String value, final TypeLiteral toType ) + { + final String text = value.trim(); + + final Class rawType = toType.getRawType(); + if ( rawType.isAssignableFrom( String.class ) ) + { + return text; // compatible type => no conversion needed + } + + // use temporary Key as quick way to auto-box primitive types into their equivalent object types + final TypeLiteral boxedType = rawType.isPrimitive() ? Key.get( rawType ).getTypeLiteral() : toType; + + for ( final TypeConverterBinding b : typeConverterBindings ) + { + if ( b.getTypeMatcher().matches( boxedType ) ) + { + return b.getTypeConverter().convert( text, toType ); + } + } + + // last chance => attempt to create an instance of the expected type: use the string if non-empty + return text.length() == 0 ? newImplementation( rawType ) : newImplementation( rawType, text ); + } +} diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml index 5d60f511df12..011bd26ec168 100644 --- a/maven-model-builder/pom.xml +++ b/maven-model-builder/pom.xml @@ -34,6 +34,11 @@ under the License. The effective model builder, with inheritance, profile activation, interpolation, ... + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT + org.codehaus.plexus plexus-utils diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index de84b90de03f..3e21fc72e735 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -55,7 +56,7 @@ import org.apache.maven.model.Dependency; import org.apache.maven.model.DependencyManagement; import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputSource; +import org.apache.maven.api.model.InputSource; import org.apache.maven.model.Model; import org.apache.maven.model.Parent; import org.apache.maven.model.Plugin; @@ -67,11 +68,11 @@ import org.apache.maven.model.composition.DependencyManagementImporter; import org.apache.maven.model.inheritance.InheritanceAssembler; import org.apache.maven.model.interpolation.ModelInterpolator; +import org.apache.maven.model.interpolation.ModelVersionProcessor; import org.apache.maven.model.io.ModelParseException; import org.apache.maven.model.io.ModelReader; import org.apache.maven.model.management.DependencyManagementInjector; import org.apache.maven.model.management.PluginManagementInjector; -import org.apache.maven.model.merge.ModelMerger; import org.apache.maven.model.normalization.ModelNormalizer; import org.apache.maven.model.path.ModelPathTranslator; import org.apache.maven.model.path.ModelUrlNormalizer; @@ -89,6 +90,7 @@ import org.apache.maven.model.resolution.UnresolvableModelException; import org.apache.maven.model.resolution.WorkspaceModelResolver; import org.apache.maven.model.superpom.SuperPomProvider; +import org.apache.maven.model.v4.MavenMerger; import org.apache.maven.model.validation.ModelValidator; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.MapBasedValueSource; @@ -101,9 +103,9 @@ @Named @Singleton public class DefaultModelBuilder - implements ModelBuilder + implements ModelBuilder { - private final ModelMerger modelMerger = new FileToRawModelMerger(); + private final MavenMerger modelMerger = new FileToRawModelMerger(); private final ModelProcessor modelProcessor; private final ModelValidator modelValidator; @@ -123,7 +125,9 @@ public class DefaultModelBuilder private final ReportConfigurationExpander reportConfigurationExpander; private final ReportingConverter reportingConverter; private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; + private final ModelVersionProcessor versionProcessor; + @SuppressWarnings( "checkstyle:ParameterNumber" ) @Inject public DefaultModelBuilder( ModelProcessor modelProcessor, @@ -143,7 +147,8 @@ public DefaultModelBuilder( PluginConfigurationExpander pluginConfigurationExpander, ReportConfigurationExpander reportConfigurationExpander, ReportingConverter reportingConverter, - ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator ) + ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator, + ModelVersionProcessor versionProcessor ) { this.modelProcessor = modelProcessor; this.modelValidator = modelValidator; @@ -163,6 +168,7 @@ public DefaultModelBuilder( this.reportConfigurationExpander = reportConfigurationExpander; this.reportingConverter = reportingConverter; this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator; + this.versionProcessor = versionProcessor; } /** @@ -176,7 +182,7 @@ public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -190,7 +196,7 @@ public DefaultModelBuilder setModelValidator( ModelValidator modelValidator ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -204,7 +210,7 @@ public DefaultModelBuilder setModelNormalizer( ModelNormalizer modelNormalizer ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -218,7 +224,7 @@ public DefaultModelBuilder setModelInterpolator( ModelInterpolator modelInterpol modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -232,7 +238,7 @@ public DefaultModelBuilder setModelPathTranslator( ModelPathTranslator modelPath modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -246,7 +252,7 @@ public DefaultModelBuilder setModelUrlNormalizer( ModelUrlNormalizer modelUrlNor modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -260,7 +266,7 @@ public DefaultModelBuilder setSuperPomProvider( SuperPomProvider superPomProvide modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -274,7 +280,7 @@ public DefaultModelBuilder setInheritanceAssembler( InheritanceAssembler inherit modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -288,7 +294,7 @@ public DefaultModelBuilder setProfileSelector( ProfileSelector profileSelector ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -302,7 +308,7 @@ public DefaultModelBuilder setProfileInjector( ProfileInjector profileInjector ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -316,7 +322,7 @@ public DefaultModelBuilder setPluginManagementInjector( PluginManagementInjector modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -331,7 +337,7 @@ public DefaultModelBuilder setDependencyManagementInjector( modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -346,7 +352,7 @@ public DefaultModelBuilder setDependencyManagementImporter( modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -360,7 +366,7 @@ public DefaultModelBuilder setLifecycleBindingsInjector( LifecycleBindingsInject modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -374,7 +380,7 @@ public DefaultModelBuilder setPluginConfigurationExpander( PluginConfigurationEx modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -388,7 +394,7 @@ public DefaultModelBuilder setReportConfigurationExpander( ReportConfigurationEx modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -402,7 +408,7 @@ public DefaultModelBuilder setReportingConverter( ReportingConverter reportingCo modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -417,7 +423,7 @@ public DefaultModelBuilder setProfileActivationFilePathInterpolator( modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } @Override @@ -462,8 +468,8 @@ else if ( hasModelErrors( problems ) ) } private void activateFileModel( final ModelBuildingRequest request, final DefaultModelBuildingResult result, - DefaultModelProblemCollector problems ) - throws ModelBuildingException + DefaultModelProblemCollector problems ) + throws ModelBuildingException { Model inputModel = request.getFileModel(); problems.setRootModel( inputModel ); @@ -495,7 +501,7 @@ private void activateFileModel( final ModelBuildingRequest request, final Defaul // model normalization problems.setSource( inputModel ); - modelNormalizer.mergeDuplicates( inputModel, request, problems ); + inputModel.update( modelNormalizer.mergeDuplicates( inputModel.getDelegate(), request, problems ) ); Map interpolatedActivations = getProfileActivations( inputModel, false ); injectProfileActivations( inputModel, interpolatedActivations ); @@ -564,7 +570,7 @@ private Model readEffectiveModel( final ModelBuildingRequest request, final Defa problems.setSource( tmpModel ); // model normalization - modelNormalizer.mergeDuplicates( tmpModel, request, problems ); + tmpModel = new Model( modelNormalizer.mergeDuplicates( tmpModel.getDelegate(), request, problems ) ); profileActivationContext.setProjectProperties( tmpModel.getProperties() ); @@ -628,9 +634,7 @@ else if ( !parentIds.add( parentData.getId() ) ) checkPluginVersions( lineage, request, problems ); // inheritance assembly - assembleInheritance( lineage, request, problems ); - - Model resultModel = lineage.get( 0 ); + Model resultModel = assembleInheritance( lineage, request, problems ); // consider caching inherited model @@ -746,7 +750,7 @@ private ModelBuildingResult build( final ModelBuildingRequest request, final Mod // dependency management injection dependencyManagementInjector.injectManagement( resultModel, request, problems ); - modelNormalizer.injectDefaultValues( resultModel, request, problems ); + resultModel.update( modelNormalizer.injectDefaultValues( resultModel.getDelegate(), request, problems ) ); if ( request.isProcessPlugins() ) { @@ -806,7 +810,7 @@ private Model readFileModel( ModelBuildingRequest request, throws ModelBuildingException { ModelSource modelSource = request.getModelSource(); - Model model = fromCache( request.getModelCache(), modelSource, ModelCacheTag.FILE ); + org.apache.maven.api.model.Model model = fromCache( request.getModelCache(), modelSource, ModelCacheTag.FILE ); if ( model == null ) { model = doReadFileModel( modelSource, request, problems ); @@ -824,15 +828,15 @@ private Model readFileModel( ModelBuildingRequest request, } } - return model; + return new Model( model ); } @SuppressWarnings( "checkstyle:methodlength" ) - private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest request, - DefaultModelProblemCollector problems ) + private org.apache.maven.api.model.Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest request, + DefaultModelProblemCollector problems ) throws ModelBuildingException { - Model model; + org.apache.maven.api.model.Model model; problems.setSource( modelSource.getLocation() ); try { @@ -845,7 +849,8 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req InputSource source; if ( request.isLocationTracking() ) { - source = (InputSource) options.computeIfAbsent( ModelProcessor.INPUT_SOURCE, k -> new InputSource() ); + source = new InputSource( null, modelSource.getLocation() ); + options.put( ModelProcessor.INPUT_SOURCE, source ); } else { @@ -883,8 +888,17 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req if ( source != null ) { - source.setModelId( ModelProblemUtils.toId( model ) ); - source.setLocation( modelSource.getLocation() ); + try + { + Field field = InputSource.class.getDeclaredField( "modelId" ); + field.setAccessible( true ); + field.set( source, ModelProblemUtils.toId( model ) ); + } + catch ( Throwable t ) + { + // TODO: use a lazy source ? + throw new IllegalStateException( "Unable to set modelId on InputSource", t ); + } } } catch ( ModelParseException e ) @@ -916,11 +930,14 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req if ( modelSource instanceof FileModelSource ) { - model.setPomFile( ( (FileModelSource) modelSource ).getFile() ); + model = model.withPomFile( ( (FileModelSource) modelSource ).getFile().toPath() ); } - problems.setSource( model ); - modelValidator.validateFileModel( model, request, problems ); + Model retModel = new Model( model ); + + problems.setSource( retModel ); + + modelValidator.validateFileModel( retModel, request, problems ); if ( hasFatalErrors( problems ) ) { @@ -957,13 +974,14 @@ private Model readRawModel( ModelBuildingRequest request, DefaultModelProblemCol try { // must implement TransformContext, but should use request to access system properties/modelcache - Model transformedFileModel = modelProcessor.read( pomFile, - Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) ); + org.apache.maven.api.model.Model transformedFileModel = modelProcessor.read( pomFile, + Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) ); // rawModel with locationTrackers, required for proper feedback during validations // Apply enriched data - modelMerger.merge( rawModel, transformedFileModel, false, null ); + rawModel = new Model( modelMerger.merge( rawModel.getDelegate(), + transformedFileModel, false, null ) ); } catch ( IOException e ) { @@ -997,6 +1015,11 @@ else if ( request.getFileModel() == null ) } private String getGroupId( Model model ) + { + return getGroupId( model.getDelegate() ); + } + + private String getGroupId( org.apache.maven.api.model.Model model ) { String groupId = model.getGroupId(); if ( groupId == null && model.getParent() != null ) @@ -1055,8 +1078,8 @@ private void configureResolver( ModelResolver modelResolver, Model model, Defaul catch ( InvalidRepositoryException e ) { problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ) - .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() ) - .setLocation( repository.getLocation( "" ) ).setException( e ) ); + .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() ) + .setLocation( repository.getLocation( "" ) ).setException( e ) ); } } } @@ -1113,15 +1136,16 @@ private void checkPluginVersions( List lineage, ModelBuildingRequest requ } } - private void assembleInheritance( List lineage, ModelBuildingRequest request, + private Model assembleInheritance( List lineage, ModelBuildingRequest request, ModelProblemCollector problems ) { + org.apache.maven.api.model.Model parent = lineage.get( lineage.size() - 1 ).getDelegate(); for ( int i = lineage.size() - 2; i >= 0; i-- ) { - Model parent = lineage.get( i + 1 ); Model child = lineage.get( i ); - inheritanceAssembler.assembleModelInheritance( child, parent, request, problems ); + parent = inheritanceAssembler.assembleModelInheritance( child.getDelegate(), parent, request, problems ); } + return new Model( parent ); } private Map getProfileActivations( Model model, boolean clone ) @@ -1168,8 +1192,8 @@ private Model interpolateModel( Model model, ModelBuildingRequest request, Model // save profile activations before interpolation, since they are evaluated with limited scope Map originalActivations = getProfileActivations( model, true ); - Model interpolatedModel = - modelInterpolator.interpolateModel( model, model.getProjectDirectory(), request, problems ); + Model interpolatedModel = new Model( modelInterpolator.interpolateModel( + model.getDelegate(), model.getProjectDirectory(), request, problems ) ); if ( interpolatedModel.getParent() != null ) { StringSearchInterpolator ssi = new StringSearchInterpolator(); @@ -1187,10 +1211,10 @@ private Model interpolateModel( Model model, ModelBuildingRequest request, Model catch ( Exception e ) { ModelProblemCollectorRequest mpcr = - new ModelProblemCollectorRequest( Severity.ERROR, - Version.BASE ).setMessage( "Failed to interpolate field: " - + interpolatedModel.getParent().getVersion() - + " on class: " ).setException( e ); + new ModelProblemCollectorRequest( Severity.ERROR, + Version.BASE ).setMessage( "Failed to interpolate field: " + + interpolatedModel.getParent().getVersion() + + " on class: " ).setException( e ); problems.add( mpcr ); } @@ -1481,7 +1505,7 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r private Model getSuperModel() { - return superPomProvider.getSuperModel( "4.0.0" ).clone(); + return new Model( superPomProvider.getSuperModel( "4.0.0" ) ); } private void importDependencyManagement( Model model, ModelBuildingRequest request, @@ -1498,7 +1522,7 @@ private void importDependencyManagement( Model model, ModelBuildingRequest reque importIds.add( importing ); - List importMgmts = null; + List importMgmts = null; for ( Iterator it = depMgmt.getDependencies().iterator(); it.hasNext(); ) { @@ -1512,7 +1536,7 @@ private void importDependencyManagement( Model model, ModelBuildingRequest reque it.remove(); DependencyManagement importMgmt = loadDependencyManagement( model, request, problems, - dependency, importIds ); + dependency, importIds ); if ( importMgmt != null ) { @@ -1521,13 +1545,14 @@ private void importDependencyManagement( Model model, ModelBuildingRequest reque importMgmts = new ArrayList<>(); } - importMgmts.add( importMgmt ); + importMgmts.add( importMgmt.getDelegate() ); } } importIds.remove( importing ); - dependencyManagementImporter.importManagement( model, importMgmts, request, problems ); + model.update( dependencyManagementImporter.importManagement( + model.getDelegate(), importMgmts, request, problems ) ); } private DependencyManagement loadDependencyManagement( Model model, ModelBuildingRequest request, @@ -1581,19 +1606,21 @@ private DependencyManagement loadDependencyManagement( Model model, ModelBuildin return null; } - DependencyManagement importMgmt = fromCache( request.getModelCache(), groupId, artifactId, version, - ModelCacheTag.IMPORT ); + org.apache.maven.api.model.DependencyManagement importMgmt = + fromCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT ); if ( importMgmt == null ) { - importMgmt = doLoadDependencyManagement( model, request, problems, dependency, - groupId, artifactId, version, importIds ); - if ( importMgmt != null ) + DependencyManagement importMgmtV3 = doLoadDependencyManagement( model, request, problems, dependency, + groupId, artifactId, version, importIds ); + if ( importMgmtV3 != null ) { - intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt ); + importMgmt = importMgmtV3.getDelegate(); + intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, + importMgmt ); } } - return importMgmt; + return importMgmt != null ? new DependencyManagement( importMgmt ) : null; } @SuppressWarnings( "checkstyle:parameternumber" ) @@ -1836,7 +1863,14 @@ private Model findRawModel( String groupId, String artifactId ) { ModelBuildingRequest gaBuildingRequest = new DefaultModelBuildingRequest( request ) .setModelSource( (ModelSource) source ); - return readRawModel( gaBuildingRequest, problems ); + Model model = readRawModel( gaBuildingRequest, problems ); + if ( source instanceof FileModelSource ) + { + Path path = ( ( FileModelSource ) source ).getFile().toPath(); + context.modelByPath.computeIfAbsent( path, k -> new DefaultTransformerContext.Holder() ) + .computeIfAbsent( () -> model ); + } + return model; } catch ( ModelBuildingException e ) { @@ -1859,7 +1893,12 @@ private Model findRawModel( Path p ) try { - return readRawModel( req, problems ); + Model model = readRawModel( req, problems ); + DefaultTransformerContext.GAKey key = + new DefaultTransformerContext.GAKey( getGroupId( model ), model.getArtifactId() ); + context.modelByGA.computeIfAbsent( key, k -> new DefaultTransformerContext.Holder() ) + .computeIfAbsent( () -> model ); + return model; } catch ( ModelBuildingException e ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java index 8c7b603ab42c..397e1c6992da 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java @@ -101,6 +101,7 @@ public class DefaultModelBuilderFactory private ReportConfigurationExpander reportConfigurationExpander; private ReportingConverter reportingConverter; private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; + private ModelVersionProcessor versionProcessor; public DefaultModelBuilderFactory setModelProcessor( ModelProcessor modelProcessor ) { @@ -216,6 +217,12 @@ public DefaultModelBuilderFactory setProfileActivationFilePathInterpolator( return this; } + public DefaultModelBuilderFactory setVersionProcessor( ModelVersionProcessor versionProcessor ) + { + this.versionProcessor = versionProcessor; + return this; + } + protected ModelProcessor newModelProcessor() { return new DefaultModelProcessor( newModelLocator(), newModelReader() ); @@ -261,8 +268,7 @@ protected ModelInterpolator newModelInterpolator() { UrlNormalizer normalizer = newUrlNormalizer(); PathTranslator pathTranslator = newPathTranslator(); - ModelVersionProcessor versionProcessor = newModelVersionPropertiesProcessor(); - return new StringVisitorModelInterpolator( pathTranslator, normalizer, versionProcessor ); + return new StringVisitorModelInterpolator( pathTranslator, normalizer ); } protected ModelVersionProcessor newModelVersionPropertiesProcessor() @@ -372,7 +378,8 @@ public DefaultModelBuilder newInstance() reportConfigurationExpander != null ? reportConfigurationExpander : newReportConfigurationExpander(), reportingConverter != null ? reportingConverter : newReportingConverter(), profileActivationFilePathInterpolator != null - ? profileActivationFilePathInterpolator : newProfileActivationFilePathInterpolator() + ? profileActivationFilePathInterpolator : newProfileActivationFilePathInterpolator(), + versionProcessor != null ? versionProcessor : newModelVersionPropertiesProcessor() ); } @@ -381,7 +388,9 @@ private static class StubLifecycleBindingsInjector { @Override - public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectLifecycleBindings( Model model, + ModelBuildingRequest request, + ModelProblemCollector problems ) { } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java index 01d23ef3b669..c88df754754d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java @@ -30,7 +30,7 @@ class DefaultModelBuildingEvent implements ModelBuildingEvent { - private final Model model; + private Model model; private final ModelBuildingRequest request; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java index 168612d399c5..82af820d0eaa 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java @@ -29,7 +29,7 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.io.ModelReader; import org.apache.maven.model.locator.ModelLocator; import org.eclipse.sisu.Typed; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java index 47af900a9aa6..2609c91efd12 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java @@ -21,20 +21,21 @@ import java.util.Iterator; import java.util.Map; - -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.merge.ModelMerger; +import java.util.stream.Collectors; + +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.CiManagement; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.Reporting; +import org.apache.maven.model.v4.MavenMerger; /** * As long as Maven controls the BuildPomXMLFilter, the entities that need merging are known. @@ -43,11 +44,12 @@ * @author Robert Scholte * @since 4.0.0 */ -class FileToRawModelMerger extends ModelMerger +class FileToRawModelMerger extends MavenMerger { @Override - protected void mergeBuild_Extensions( Build target, Build source, boolean sourceDominant, + protected void mergeBuild_Extensions( Build.Builder builder, + Build target, Build source, boolean sourceDominant, Map context ) { // don't merge @@ -55,134 +57,156 @@ protected void mergeBuild_Extensions( Build target, Build source, boolean source @Override - protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant, + protected void mergeBuildBase_Resources( BuildBase.Builder builder, + BuildBase target, BuildBase source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant, + protected void mergeBuildBase_TestResources( BuildBase.Builder builder, + BuildBase target, BuildBase source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeCiManagement_Notifiers( CiManagement target, CiManagement source, boolean sourceDominant, + protected void mergeCiManagement_Notifiers( CiManagement.Builder builder, + CiManagement target, CiManagement source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source, + protected void mergeDependencyManagement_Dependencies( DependencyManagement.Builder builder, + DependencyManagement target, DependencyManagement source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); - target.getDependencies().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.dependencies( target.getDependencies().stream() + .map( d -> mergeDependency( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override - protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, + protected void mergeDependency_Exclusions( Dependency.Builder builder, + Dependency target, Dependency source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Contributors( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Developers( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Licenses( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant, + protected void mergeModel_MailingLists( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Profiles( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getProfiles().iterator(); - target.getProfiles().forEach( t -> mergeProfile( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.profiles( target.getProfiles().stream() + .map( d -> mergeProfile( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override - protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_Dependencies( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); - target.getDependencies().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.dependencies( target.getDependencies().stream() + .map( d -> mergeDependency( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override - protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_PluginRepositories( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { - target.setPluginRepositories( source.getPluginRepositories() ); + builder.pluginRepositories( source.getPluginRepositories() ); } @Override - protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_Repositories( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean sourceDominant, + protected void mergePlugin_Dependencies( Plugin.Builder builder, + Plugin target, Plugin source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); - target.getDependencies().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.dependencies( target.getDependencies().stream() + .map( d -> mergeDependency( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, + protected void mergePlugin_Executions( Plugin.Builder builder, + Plugin target, Plugin source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, + protected void mergeReporting_Plugins( Reporting.Builder builder, + Reporting target, Reporting source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, + protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, + ReportPlugin target, ReportPlugin source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, boolean sourceDominant, Map context ) { // don't merge diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java index 7e0cb0daa441..fcde1c3a650a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; /** * Describes a tag used by the model builder to access a {@link ModelCache}. This interface basically aggregates a name @@ -85,14 +85,13 @@ public Class getType() @Override public ModelData intoCache( ModelData data ) { - Model model = ( data.getModel() != null ) ? data.getModel().clone() : null; - return new ModelData( data.getSource(), model, data.getGroupId(), data.getArtifactId(), data.getVersion() ); + return data; } @Override public ModelData fromCache( ModelData data ) { - return intoCache( data ); + return data; } }; @@ -118,13 +117,13 @@ public Class getType() @Override public DependencyManagement intoCache( DependencyManagement data ) { - return ( data != null ) ? data.clone() : null; + return data; } @Override public DependencyManagement fromCache( DependencyManagement data ) { - return intoCache( data ); + return data; } }; @@ -150,13 +149,13 @@ public Class getType() @Override public Model intoCache( Model data ) { - return ( data != null ) ? data.clone() : null; + return data; } @Override public Model fromCache( Model data ) { - return intoCache( data ); + return data; } }; } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java index 150d60dcf49c..d853503ee155 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java @@ -80,7 +80,11 @@ static String toId( Model model ) { return ""; } + return toId( model.getDelegate() ); + } + static String toId( org.apache.maven.api.model.Model model ) + { String groupId = model.getGroupId(); if ( groupId == null && model.getParent() != null ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index b277bf3a1caf..d817c99a919d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -19,7 +19,6 @@ * under the License. */ -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -27,9 +26,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -45,7 +44,7 @@ public class DefaultDependencyManagementImporter { @Override - public void importManagement( Model target, List sources, + public Model importManagement( Model target, List sources, ModelBuildingRequest request, ModelProblemCollector problems ) { if ( sources != null && !sources.isEmpty() ) @@ -63,8 +62,7 @@ public void importManagement( Model target, List } else { - depMgmt = new DependencyManagement(); - target.setDependencyManagement( depMgmt ); + depMgmt = DependencyManagement.newInstance(); } for ( DependencyManagement source : sources ) @@ -72,15 +70,14 @@ public void importManagement( Model target, List for ( Dependency dependency : source.getDependencies() ) { String key = dependency.getManagementKey(); - if ( !dependencies.containsKey( key ) ) - { - dependencies.put( key, dependency ); - } + dependencies.putIfAbsent( key, dependency ); } } - depMgmt.setDependencies( new ArrayList<>( dependencies.values() ) ); + return target.withDependencyManagement( + depMgmt.withDependencies( dependencies.values() ) ); } + return target; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java index 06496429d1e4..076c19312beb 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -42,7 +42,7 @@ public interface DependencyManagementImporter * @param request The model building request that holds further settings, must not be {@code null}. * @param problems The container used to collect problems that were encountered, must not be {@code null}. */ - void importManagement( Model target, List sources, ModelBuildingRequest request, + Model importManagement( Model target, List sources, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java index ae5ac0b7ac25..20b3fc59cd24 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java @@ -29,13 +29,13 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.Reporting; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -60,14 +60,14 @@ public class DefaultInheritanceAssembler private static final String CHILD_DIRECTORY_PROPERTY = "project.directory"; @Override - public void assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, + public Model assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, ModelProblemCollector problems ) { Map hints = new HashMap<>(); String childPath = child.getProperties().getProperty( CHILD_DIRECTORY_PROPERTY, child.getArtifactId() ); hints.put( CHILD_DIRECTORY, childPath ); hints.put( MavenModelMerger.CHILD_PATH_ADJUSTMENT, getChildPathAdjustment( child, parent, childPath ) ); - merger.merge( child, parent, false, hints ); + return merger.merge( child, parent, false, hints ); } /** @@ -106,7 +106,7 @@ private String getChildPathAdjustment( Model child, Model parent, String childDi */ if ( child.getProjectDirectory() != null ) { - childName = child.getProjectDirectory().getName(); + childName = child.getProjectDirectory().getFileName().toString(); } for ( String module : parent.getModules() ) @@ -206,7 +206,8 @@ else if ( !initialUrlEndsWithSlash ) } @Override - protected void mergeModelBase_Properties( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_Properties( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { Properties merged = new Properties(); @@ -220,8 +221,8 @@ protected void mergeModelBase_Properties( ModelBase target, ModelBase source, bo putAll( merged, source.getProperties(), CHILD_DIRECTORY_PROPERTY ); merged.putAll( target.getProperties() ); } - target.setProperties( merged ); - target.setLocation( "properties", + builder.properties( merged ); + builder.location( "properties", InputLocation.merge( target.getLocation( "properties" ), source.getLocation( "properties" ), sourceDominant ) ); } @@ -238,7 +239,8 @@ private void putAll( Map s, Map t, Object exclud } @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, boolean sourceDominant, Map context ) { List src = source.getPlugins(); @@ -252,12 +254,10 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta if ( element.isInherited() || !element.getExecutions().isEmpty() ) { // NOTE: Enforce recursive merge to trigger merging/inheritance logic for executions - Plugin plugin = new Plugin(); - plugin.setLocation( "", element.getLocation( "" ) ); - plugin.setGroupId( null ); - mergePlugin( plugin, element, sourceDominant, context ); + Plugin plugin = Plugin.newInstance( false ); + plugin = mergePlugin( plugin, element, sourceDominant, context ); - Object key = getPluginKey().apply( element ); + Object key = getPluginKey().apply( plugin ); master.put( key, plugin ); } @@ -271,7 +271,7 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin existing = master.get( key ); if ( existing != null ) { - mergePlugin( element, existing, sourceDominant, context ); + element = mergePlugin( element, existing, sourceDominant, context ); master.put( key, element ); @@ -299,27 +299,31 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta } result.addAll( pending ); - target.setPlugins( result ); + builder.plugins( result ); } } @Override - protected void mergePlugin( Plugin target, Plugin source, boolean sourceDominant, Map context ) + protected Plugin mergePlugin( Plugin target, Plugin source, + boolean sourceDominant, Map context ) { + Plugin.Builder builder = Plugin.newBuilder( target ); if ( source.isInherited() ) { - mergeConfigurationContainer( target, source, sourceDominant, context ); + mergeConfigurationContainer( builder, target, source, sourceDominant, context ); } - mergePlugin_GroupId( target, source, sourceDominant, context ); - mergePlugin_ArtifactId( target, source, sourceDominant, context ); - mergePlugin_Version( target, source, sourceDominant, context ); - mergePlugin_Extensions( target, source, sourceDominant, context ); - mergePlugin_Dependencies( target, source, sourceDominant, context ); - mergePlugin_Executions( target, source, sourceDominant, context ); + mergePlugin_GroupId( builder, target, source, sourceDominant, context ); + mergePlugin_ArtifactId( builder, target, source, sourceDominant, context ); + mergePlugin_Version( builder, target, source, sourceDominant, context ); + mergePlugin_Extensions( builder, target, source, sourceDominant, context ); + mergePlugin_Executions( builder, target, source, sourceDominant, context ); + mergePlugin_Dependencies( builder, target, source, sourceDominant, context ); + return builder.build(); } @Override - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, + protected void mergeReporting_Plugins( Reporting.Builder builder, + Reporting target, Reporting source, boolean sourceDominant, Map context ) { List src = source.getPlugins(); @@ -331,16 +335,13 @@ protected void mergeReporting_Plugins( Reporting target, Reporting source, boole for ( ReportPlugin element : src ) { - Object key = getReportPluginKey().apply( element ); if ( element.isInherited() ) { // NOTE: Enforce recursive merge to trigger merging/inheritance logic for executions as well - ReportPlugin plugin = new ReportPlugin(); - plugin.setLocation( "", element.getLocation( "" ) ); - plugin.setGroupId( null ); - mergeReportPlugin( plugin, element, sourceDominant, context ); + ReportPlugin plugin = ReportPlugin.newInstance(); + plugin = mergeReportPlugin( plugin, element, sourceDominant, context ); - merged.put( key, plugin ); + merged.put( getReportPluginKey().apply( element ), plugin ); } } @@ -350,12 +351,12 @@ protected void mergeReporting_Plugins( Reporting target, Reporting source, boole ReportPlugin existing = merged.get( key ); if ( existing != null ) { - mergeReportPlugin( element, existing, sourceDominant, context ); + element = mergeReportPlugin( element, existing, sourceDominant, context ); } merged.put( key, element ); } - target.setPlugins( new ArrayList<>( merged.values() ) ); + builder.plugins( merged.values() ); } } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java index a191e52dd1d6..0badb7a58bb0 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -42,7 +42,7 @@ public interface InheritanceAssembler * @param request The model building request that holds further settings, must not be {@code null}. * @param problems The container used to collect problems that were encountered, must not be {@code null}. */ - void assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, + Model assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java index e42e6e3b636d..749033b14d17 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java @@ -29,8 +29,9 @@ import javax.inject.Inject; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; +import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.path.PathTranslator; import org.apache.maven.model.path.UrlNormalizer; import org.codehaus.plexus.interpolation.AbstractValueSource; @@ -76,15 +77,20 @@ public abstract class AbstractStringBasedModelInterpolator private final PathTranslator pathTranslator; private final UrlNormalizer urlNormalizer; - private final ModelVersionProcessor versionProcessor; @Inject - public AbstractStringBasedModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer, - ModelVersionProcessor processor ) + public AbstractStringBasedModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer ) { this.pathTranslator = pathTranslator; this.urlNormalizer = urlNormalizer; - this.versionProcessor = processor; + } + + @Override + public org.apache.maven.model.Model interpolateModel( org.apache.maven.model.Model model, File projectDir, + ModelBuildingRequest request, ModelProblemCollector problems ) + { + return new org.apache.maven.model.Model( interpolateModel( model.getDelegate(), projectDir, + request, problems ) ); } protected List createValueSources( final Model model, final File projectDir, @@ -133,10 +139,6 @@ public Object getValue( String expression ) valueSources.add( new MapBasedValueSource( config.getUserProperties() ) ); - // Overwrite existing values in model properties. Otherwise it's not possible - // to define the version via command line: mvn -Drevision=6.5.7 ... - versionProcessor.overwriteModelProperties( modelProperties, config ); - valueSources.add( new MapBasedValueSource( modelProperties ) ); valueSources.add( new MapBasedValueSource( config.getSystemProperties() ) ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java index 5fc4c9c6791e..25de5ef939c5 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -49,4 +49,7 @@ public interface ModelInterpolator Model interpolateModel( Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems ); + org.apache.maven.model.Model interpolateModel( org.apache.maven.model.Model model, File projectDir, + ModelBuildingRequest request, ModelProblemCollector problems ); + } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java deleted file mode 100644 index d996097232c9..000000000000 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java +++ /dev/null @@ -1,527 +0,0 @@ -package org.apache.maven.model.interpolation; - -/* - * 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. - */ - -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.Model; -import org.apache.maven.model.building.ModelBuildingRequest; -import org.apache.maven.model.building.ModelProblem.Severity; -import org.apache.maven.model.building.ModelProblem.Version; -import org.apache.maven.model.building.ModelProblemCollector; -import org.apache.maven.model.building.ModelProblemCollectorRequest; -import org.apache.maven.model.path.PathTranslator; -import org.apache.maven.model.path.UrlNormalizer; -import org.codehaus.plexus.interpolation.InterpolationException; -import org.codehaus.plexus.interpolation.InterpolationPostProcessor; -import org.codehaus.plexus.interpolation.RecursionInterceptor; -import org.codehaus.plexus.interpolation.StringSearchInterpolator; -import org.codehaus.plexus.interpolation.ValueSource; - -import java.io.File; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.inject.Inject; - -/** - * StringSearchModelInterpolator - * @deprecated replaced by StringVisitorModelInterpolator (MNG-6697) - */ -@Deprecated -public class StringSearchModelInterpolator - extends AbstractStringBasedModelInterpolator -{ - private static final Map, InterpolateObjectAction.CacheItem> CACHED_ENTRIES = - new ConcurrentHashMap<>( 80, 0.75f, 2 ); - // Empirical data from 3.x, actual =40 - - private interface InnerInterpolator - { - String interpolate( String value ); - } - - @Inject - public StringSearchModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer, - ModelVersionProcessor processor ) - { - super( pathTranslator, urlNormalizer, processor ); - } - - @Override - public Model interpolateModel( Model model, File projectDir, ModelBuildingRequest config, - ModelProblemCollector problems ) - { - interpolateObject( model, model, projectDir, config, problems ); - return model; - } - - void interpolateObject( Object obj, Model model, File projectDir, ModelBuildingRequest config, - ModelProblemCollector problems ) - { - List valueSources = createValueSources( model, projectDir, config ); - List postProcessors = createPostProcessors( model, projectDir, config ); - - InnerInterpolator innerInterpolator = createInterpolator( valueSources, postProcessors, problems ); - - PrivilegedAction action = new InterpolateObjectAction( obj, innerInterpolator, problems ); - AccessController.doPrivileged( action ); - } - - private InnerInterpolator createInterpolator( List valueSources, - List postProcessors, - final ModelProblemCollector problems ) - { - final Map cache = new HashMap<>(); - final StringSearchInterpolator interpolator = new StringSearchInterpolator(); - interpolator.setCacheAnswers( true ); - for ( ValueSource vs : valueSources ) - { - interpolator.addValueSource( vs ); - } - for ( InterpolationPostProcessor postProcessor : postProcessors ) - { - interpolator.addPostProcessor( postProcessor ); - } - final RecursionInterceptor recursionInterceptor = createRecursionInterceptor(); - return value -> - { - if ( value != null && value.contains( "${" ) ) - { - String c = cache.get( value ); - if ( c == null ) - { - try - { - c = interpolator.interpolate( value, recursionInterceptor ); - } - catch ( InterpolationException e ) - { - problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ) - .setMessage( e.getMessage() ).setException( e ) ); - } - cache.put( value, c ); - } - return c; - } - return value; - }; - } - - private static final class InterpolateObjectAction - implements PrivilegedAction - { - private final LinkedList interpolationTargets; - - private final InnerInterpolator interpolator; - - private final ModelProblemCollector problems; - - InterpolateObjectAction( Object target, InnerInterpolator interpolator, ModelProblemCollector problems ) - { - this.interpolationTargets = new LinkedList<>(); - interpolationTargets.add( target ); - this.interpolator = interpolator; - this.problems = problems; - } - - @Override - public Object run() - { - while ( !interpolationTargets.isEmpty() ) - { - Object obj = interpolationTargets.removeFirst(); - - traverseObjectWithParents( obj.getClass(), obj ); - } - return null; - } - - private String interpolate( String value ) - { - return interpolator.interpolate( value ); - } - - private void traverseObjectWithParents( Class cls, Object target ) - { - if ( cls == null ) - { - return; - } - - CacheItem cacheEntry = getCacheEntry( cls ); - if ( cacheEntry.isArray() ) - { - evaluateArray( target, this ); - } - else if ( cacheEntry.isQualifiedForInterpolation ) - { - cacheEntry.interpolate( target, this ); - - traverseObjectWithParents( cls.getSuperclass(), target ); - } - } - - private CacheItem getCacheEntry( Class cls ) - { - CacheItem cacheItem = CACHED_ENTRIES.get( cls ); - if ( cacheItem == null ) - { - cacheItem = new CacheItem( cls ); - CACHED_ENTRIES.put( cls, cacheItem ); - } - return cacheItem; - } - - private static void evaluateArray( Object target, InterpolateObjectAction ctx ) - { - int len = Array.getLength( target ); - for ( int i = 0; i < len; i++ ) - { - Object value = Array.get( target, i ); - if ( value != null ) - { - if ( String.class == value.getClass() ) - { - String interpolated = ctx.interpolate( (String) value ); - - if ( !interpolated.equals( value ) ) - { - Array.set( target, i, interpolated ); - } - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - - private static class CacheItem - { - private final boolean isArray; - - private final boolean isQualifiedForInterpolation; - - private final CacheField[] fields; - - private boolean isQualifiedForInterpolation( Class cls ) - { - Package pkg = cls.getPackage(); - if ( pkg == null ) - { - return true; - } - String pkgName = pkg.getName(); - return !pkgName.startsWith( "java." ) && !pkgName.startsWith( "javax." ); - } - - private boolean isQualifiedForInterpolation( Field field, Class fieldType ) - { - if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) ) - { - return false; - } - if ( InputLocation.class.equals( fieldType ) ) - { - return false; - } - - //noinspection SimplifiableIfStatement - if ( fieldType.isPrimitive() ) - { - return false; - } - - return !"parent".equals( field.getName() ); - } - - CacheItem( Class clazz ) - { - this.isQualifiedForInterpolation = isQualifiedForInterpolation( clazz ); - this.isArray = clazz.isArray(); - List fields = new ArrayList<>(); - if ( isQualifiedForInterpolation ) - { - for ( Field currentField : clazz.getDeclaredFields() ) - { - Class type = currentField.getType(); - if ( isQualifiedForInterpolation( currentField, type ) ) - { - if ( String.class == type ) - { - if ( !Modifier.isFinal( currentField.getModifiers() ) ) - { - fields.add( new StringField( currentField ) ); - } - } - else if ( List.class.isAssignableFrom( type ) ) - { - fields.add( new ListField( currentField ) ); - } - else if ( Collection.class.isAssignableFrom( type ) ) - { - throw new RuntimeException( - "We dont interpolate into collections, use a list instead" ); - } - else if ( Map.class.isAssignableFrom( type ) ) - { - fields.add( new MapField( currentField ) ); - } - else - { - fields.add( new ObjectField( currentField ) ); - } - } - } - } - this.fields = fields.toArray( new CacheField[0] ); - } - - void interpolate( Object target, InterpolateObjectAction interpolateObjectAction ) - { - for ( CacheField field : fields ) - { - field.interpolate( target, interpolateObjectAction ); - } - } - - boolean isArray() - { - return isArray; - } - } - - abstract static class CacheField - { - final Field field; - - CacheField( Field field ) - { - this.field = field; - field.setAccessible( true ); - } - - void interpolate( Object target, InterpolateObjectAction interpolateObjectAction ) - { - try - { - doInterpolate( target, interpolateObjectAction ); - } - catch ( IllegalArgumentException e ) - { - interpolateObjectAction.problems.add( - new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( - "Failed to interpolate field3: " + field + " on class: " - + field.getType().getName() ).setException( - e ) ); // TODO Not entirely the same message - } - catch ( IllegalAccessException e ) - { - interpolateObjectAction.problems.add( - new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( - "Failed to interpolate field4: " + field + " on class: " - + field.getType().getName() ).setException( e ) ); - } - } - - abstract void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException; - } - - static final class StringField - extends CacheField - { - StringField( Field field ) - { - super( field ); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - String value = (String) field.get( target ); - if ( value == null ) - { - return; - } - - String interpolated = ctx.interpolate( value ); - - if ( interpolated != null && !interpolated.equals( value ) ) - { - field.set( target, interpolated ); - } - } - } - - static final class ListField - extends CacheField - { - ListField( Field field ) - { - super( field ); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - @SuppressWarnings( "unchecked" ) List c = (List) field.get( target ); - if ( c == null ) - { - return; - } - - for ( int i = 0, size = c.size(); i < size; i++ ) - { - Object value = c.get( i ); - - if ( value != null ) - { - if ( String.class == value.getClass() ) - { - String interpolated = ctx.interpolate( (String) value ); - - if ( !interpolated.equals( value ) ) - { - try - { - c.set( i, interpolated ); - } - catch ( UnsupportedOperationException e ) - { - return; - } - } - } - else - { - if ( value.getClass().isArray() ) - { - evaluateArray( value, ctx ); - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - } - } - - static final class MapField - extends CacheField - { - MapField( Field field ) - { - super( field ); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - @SuppressWarnings( "unchecked" ) Map m = (Map) field.get( target ); - if ( m == null || m.isEmpty() ) - { - return; - } - - for ( Map.Entry entry : m.entrySet() ) - { - Object value = entry.getValue(); - - if ( value == null ) - { - continue; - } - - if ( String.class == value.getClass() ) - { - String interpolated = ctx.interpolate( (String) value ); - - if ( interpolated != null && !interpolated.equals( value ) ) - { - try - { - entry.setValue( interpolated ); - } - catch ( UnsupportedOperationException ignore ) - { - // nop - } - } - } - else if ( value.getClass().isArray() ) - { - evaluateArray( value, ctx ); - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - - static final class ObjectField - extends CacheField - { - private final boolean isArray; - - ObjectField( Field field ) - { - super( field ); - this.isArray = field.getType().isArray(); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - Object value = field.get( target ); - if ( value != null ) - { - if ( isArray ) - { - evaluateArray( value, ctx ); - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - } -} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java index 3ba48ecc501e..e84654710435 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java @@ -22,56 +22,19 @@ import java.io.File; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; -import java.util.Properties; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.ActivationOS; -import org.apache.maven.model.ActivationProperty; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.Contributor; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Developer; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Extension; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.License; -import org.apache.maven.model.MailingList; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Notifier; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Relocation; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryBase; -import org.apache.maven.model.RepositoryPolicy; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollectorRequest; +import org.apache.maven.model.v4.MavenTransformer; import org.apache.maven.model.path.PathTranslator; import org.apache.maven.model.path.UrlNormalizer; import org.codehaus.plexus.interpolation.InterpolationException; @@ -79,7 +42,6 @@ import org.codehaus.plexus.interpolation.RecursionInterceptor; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.codehaus.plexus.interpolation.ValueSource; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * StringVisitorModelInterpolator @@ -92,10 +54,10 @@ public class StringVisitorModelInterpolator extends AbstractStringBasedModelInterpolator { @Inject - public StringVisitorModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer, - ModelVersionProcessor processor ) + public StringVisitorModelInterpolator( PathTranslator pathTranslator, + UrlNormalizer urlNormalizer ) { - super( pathTranslator, urlNormalizer, processor ); + super( pathTranslator, urlNormalizer ); } interface InnerInterpolator @@ -113,9 +75,7 @@ public Model interpolateModel( Model model, File projectDir, ModelBuildingReques InnerInterpolator innerInterpolator = createInterpolator( valueSources, postProcessors, problems ); - new ModelVisitor( innerInterpolator ).visit( model ); - - return model; + return new MavenTransformer( innerInterpolator::interpolate ).visit( model ); } private InnerInterpolator createInterpolator( List valueSources, @@ -158,1307 +118,4 @@ private InnerInterpolator createInterpolator( List valueS }; } - @SuppressWarnings( "StringEquality" ) - private static final class ModelVisitor - { - private final InnerInterpolator interpolator; - - ModelVisitor( InnerInterpolator interpolator ) - { - this.interpolator = interpolator; - } - - void visit( Model model ) - { - if ( model != null ) - { - visit( (ModelBase) model ); - // ModelVersion - String orgModelVersion = model.getModelVersion(); - String intModelVersion = interpolate( orgModelVersion ); - if ( orgModelVersion != intModelVersion ) - { - model.setModelVersion( intModelVersion ); - } - visit( model.getParent() ); - // GroupId - String orgGroupId = model.getGroupId(); - String intGroupId = interpolate( orgGroupId ); - if ( orgGroupId != intGroupId ) - { - model.setGroupId( intGroupId ); - } - // ArtifactId - String orgArtifactId = model.getArtifactId(); - String intArtifactId = interpolate( orgArtifactId ); - if ( orgArtifactId != intArtifactId ) - { - model.setArtifactId( intArtifactId ); - } - // Version - String orgVersion = model.getVersion(); - String intVersion = interpolate( orgVersion ); - if ( orgVersion != intVersion ) - { - model.setVersion( intVersion ); - } - - // Packaging - String orgPackaging = model.getPackaging(); - String intPackaging = interpolate( orgPackaging ); - if ( orgPackaging != intPackaging ) - { - model.setPackaging( intPackaging ); - } - // Name - String orgName = model.getName(); - String intName = interpolate( orgName ); - if ( orgName != intName ) - { - model.setName( intName ); - } - // Description - String orgDescription = model.getDescription(); - String intDescription = interpolate( orgDescription ); - if ( orgDescription != intDescription ) - { - model.setDescription( intDescription ); - } - // Url - String orgUrl = model.getUrl(); - String intUrl = interpolate( orgUrl ); - if ( orgUrl != intUrl ) - { - model.setUrl( intUrl ); - } - // ChildProjectUrlInheritAppendPath - String orgChildProjectUrlInheritAppendPath = model.getChildProjectUrlInheritAppendPath(); - String intChildProjectUrlInheritAppendPath = interpolate( orgChildProjectUrlInheritAppendPath ); - if ( orgChildProjectUrlInheritAppendPath != intChildProjectUrlInheritAppendPath ) - { - model.setChildProjectUrlInheritAppendPath( intChildProjectUrlInheritAppendPath ); - } - // InceptionYear - String orgInceptionYear = model.getInceptionYear(); - String intInceptionYear = interpolate( orgInceptionYear ); - if ( orgInceptionYear != intInceptionYear ) - { - model.setInceptionYear( intInceptionYear ); - } - visit( model.getOrganization() ); - for ( License license : model.getLicenses() ) - { - visit( license ); - } - for ( Developer developer : model.getDevelopers() ) - { - visit( developer ); - } - for ( Contributor contributor : model.getContributors() ) - { - visit( contributor ); - } - for ( MailingList mailingList : model.getMailingLists() ) - { - visit( mailingList ); - } - visit( model.getPrerequisites() ); - visit( model.getScm() ); - visit( model.getIssueManagement() ); - visit( model.getCiManagement() ); - visit( model.getBuild() ); - for ( Profile profile : model.getProfiles() ) - { - visit( profile ); - } - - } - } - - private void visit( Parent parent ) - { - if ( parent != null ) - { - String org, val; - // GroupId - org = parent.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - parent.setGroupId( val ); - } - // ArtifactId - org = parent.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - parent.setArtifactId( val ); - } - // Version - org = parent.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - parent.setVersion( val ); - } - // RelativePath - org = parent.getRelativePath(); - val = interpolate( org ); - if ( org != val ) - { - parent.setRelativePath( val ); - } - } - } - - private void visit( Organization organization ) - { - if ( organization != null ) - { - String org, val; - // Name - org = organization.getName(); - val = interpolate( org ); - if ( org != val ) - { - organization.setName( val ); - } - // Url - org = organization.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - organization.setUrl( val ); - } - } - } - - private void visit( License license ) - { - if ( license != null ) - { - String org, val; - // Name - org = license.getName(); - val = interpolate( org ); - if ( org != val ) - { - license.setName( val ); - } - // Url - org = license.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - license.setUrl( val ); - } - // Distribution - org = license.getDistribution(); - val = interpolate( org ); - if ( org != val ) - { - license.setDistribution( val ); - } - // Comments - org = license.getComments(); - val = interpolate( org ); - if ( org != val ) - { - license.setComments( val ); - } - } - } - - private void visit( Developer developer ) - { - if ( developer != null ) - { - String org, val; - // Contributor - visit( (Contributor) developer ); - // Distribution - org = developer.getId(); - val = interpolate( org ); - if ( org != val ) - { - developer.setId( val ); - } - } - } - - private void visit( Contributor contributor ) - { - if ( contributor != null ) - { - String org, val; - // Name - org = contributor.getName(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setName( val ); - } - // Email - org = contributor.getEmail(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setEmail( val ); - } - // Url - org = contributor.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setUrl( val ); - } - // Organization - org = contributor.getOrganization(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setOrganization( val ); - } - // OrganizationUrl - org = contributor.getOrganizationUrl(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setOrganizationUrl( val ); - } - // Roles - visit( contributor.getRoles() ); - } - } - - private void visit( MailingList mailingList ) - { - if ( mailingList != null ) - { - String org, val; - // Name - org = mailingList.getName(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setName( val ); - } - // Subscribe - org = mailingList.getSubscribe(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setSubscribe( val ); - } - // Unsubscribe - org = mailingList.getUnsubscribe(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setUnsubscribe( val ); - } - // Post - org = mailingList.getPost(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setPost( val ); - } - // Archive - org = mailingList.getArchive(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setArchive( val ); - } - } - } - - private void visit( Prerequisites prerequisites ) - { - if ( prerequisites != null ) - { - String org, val; - // Maven - org = prerequisites.getMaven(); - val = interpolate( org ); - if ( org != val ) - { - prerequisites.setMaven( val ); - } - } - } - - private void visit( Scm scm ) - { - if ( scm != null ) - { - String org, val; - // Connection - org = scm.getConnection(); - val = interpolate( org ); - if ( org != val ) - { - scm.setConnection( val ); - } - // DeveloperConnection - org = scm.getDeveloperConnection(); - val = interpolate( org ); - if ( org != val ) - { - scm.setDeveloperConnection( val ); - } - // Tag - org = scm.getTag(); - val = interpolate( org ); - if ( org != val ) - { - scm.setTag( val ); - } - // Url - org = scm.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - scm.setUrl( val ); - } - // ChildScmConnectionInheritAppendPath - org = scm.getChildScmConnectionInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - scm.setChildScmConnectionInheritAppendPath( val ); - } - // ChildScmDeveloperConnectionInheritAppendPath - org = scm.getChildScmDeveloperConnectionInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - scm.setChildScmDeveloperConnectionInheritAppendPath( val ); - } - // ChildScmUrlInheritAppendPath - org = scm.getChildScmUrlInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - scm.setChildScmUrlInheritAppendPath( val ); - } - } - } - - private void visit( IssueManagement issueManagement ) - { - if ( issueManagement != null ) - { - String org, val; - // System - org = issueManagement.getSystem(); - val = interpolate( org ); - if ( org != val ) - { - issueManagement.setSystem( val ); - } - // Url - org = issueManagement.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - issueManagement.setUrl( val ); - } - } - } - - private void visit( CiManagement ciManagement ) - { - if ( ciManagement != null ) - { - String org, val; - // System - org = ciManagement.getSystem(); - val = interpolate( org ); - if ( org != val ) - { - ciManagement.setSystem( val ); - } - // Url - org = ciManagement.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - ciManagement.setUrl( val ); - } - // Notifiers - for ( Notifier notifier : ciManagement.getNotifiers() ) - { - visit( notifier ); - } - } - } - - private void visit( Notifier notifier ) - { - if ( notifier != null ) - { - String org, val; - // Type - org = notifier.getType(); - val = interpolate( org ); - if ( org != val ) - { - notifier.setType( val ); - } - // Configuration - visit( notifier.getConfiguration() ); - } - } - - private void visit( BuildBase build ) - { - if ( build != null ) - { - String org, val; - // Plugins - for ( Plugin plugin : build.getPlugins() ) - { - visit( plugin ); - } - // PluginManagement - visit( build.getPluginManagement() ); - // DefaultGoal - org = build.getDefaultGoal(); - val = interpolate( org ); - if ( org != val ) - { - build.setDefaultGoal( val ); - } - // Resources - for ( Resource resource : build.getResources() ) - { - visit( resource ); - } - // TestResources - for ( Resource resource : build.getTestResources() ) - { - visit( resource ); - } - // Directory - org = build.getDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setDirectory( val ); - } - // FinalName - org = build.getFinalName(); - val = interpolate( org ); - if ( org != val ) - { - build.setFinalName( val ); - } - // Filters - visit( build.getFilters() ); - } - } - - private void visit( PluginManagement pluginManagement ) - { - if ( pluginManagement != null ) - { - for ( Plugin plugin : pluginManagement.getPlugins() ) - { - visit( plugin ); - } - } - } - - private void visit( Build build ) - { - if ( build != null ) - { - String org, val; - // BuildBase - visit( (BuildBase) build ); - // SourceDirectory - org = build.getSourceDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setSourceDirectory( val ); - } - // ScriptSourceDirectory - org = build.getScriptSourceDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setScriptSourceDirectory( val ); - } - // TestSourceDirectory - org = build.getTestSourceDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setTestSourceDirectory( val ); - } - // OutputDirectory - org = build.getOutputDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setOutputDirectory( val ); - } - // TestOutputDirectory - org = build.getTestOutputDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setTestOutputDirectory( val ); - } - // Extensions - for ( Extension extension : build.getExtensions() ) - { - visit( extension ); - } - } - } - - private void visit( Resource resource ) - { - if ( resource != null ) - { - String org, val; - // Includes - visit( resource.getIncludes() ); - // Excludes - visit( resource.getExcludes() ); - // Directory - org = resource.getDirectory(); - val = interpolate( org ); - if ( org != val ) - { - resource.setDirectory( val ); - } - // TargetPath - org = resource.getTargetPath(); - val = interpolate( org ); - if ( org != val ) - { - resource.setTargetPath( val ); - } - // Filtering - org = resource.getFiltering(); - val = interpolate( org ); - if ( org != val ) - { - resource.setFiltering( val ); - } - } - } - - private void visit( Plugin plugin ) - { - if ( plugin != null ) - { - String org, val; - // Inherited - org = plugin.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) plugin.getConfiguration() ); - // GroupId - org = plugin.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setGroupId( val ); - } - // ArtifactId - org = plugin.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setArtifactId( val ); - } - // Version - org = plugin.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setVersion( val ); - } - // Extensions - org = plugin.getExtensions(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setExtensions( val ); - } - // Executions - for ( PluginExecution execution : plugin.getExecutions() ) - { - visit( execution ); - } - // Dependencies - for ( Dependency dependency : plugin.getDependencies() ) - { - visit( dependency ); - } - } - } - - private void visit( PluginExecution execution ) - { - if ( execution != null ) - { - String org, val; - // Inherited - org = execution.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - execution.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) execution.getConfiguration() ); - // Id - org = execution.getId(); - val = interpolate( org ); - if ( org != val ) - { - execution.setId( val ); - } - // Phase - org = execution.getPhase(); - val = interpolate( org ); - if ( org != val ) - { - execution.setPhase( val ); - } - // Goals - visit( execution.getGoals() ); - } - } - - private void visit( Xpp3Dom dom ) - { - if ( dom != null ) - { - String org, val; - // Content - org = dom.getValue(); - val = interpolate( org ); - if ( org != val ) - { - dom.setValue( val ); - } - // Attributes - for ( String attr : dom.getAttributeNames() ) - { - org = dom.getAttribute( attr ); - val = interpolate( org ); - if ( org != val ) - { - dom.setAttribute( attr, val ); - } - } - // Children - for ( int i = 0, l = dom.getChildCount(); i < l; i++ ) - { - visit( dom.getChild( i ) ); - } - } - } - - private void visit( Extension extension ) - { - if ( extension != null ) - { - String org, val; - // GroupId - org = extension.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - extension.setGroupId( val ); - } - // ArtifactId - org = extension.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - extension.setArtifactId( val ); - } - // Version - org = extension.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - extension.setVersion( val ); - } - } - } - - private void visit( Profile profile ) - { - if ( profile != null ) - { - String org, val; - // ModelBase - visit( (ModelBase) profile ); - // Id - org = profile.getId(); - val = interpolate( org ); - if ( org != val ) - { - profile.setId( val ); - } - // Activation - visit( profile.getActivation() ); - // Build - visit( profile.getBuild() ); - } - } - - private void visit( Activation activation ) - { - if ( activation != null ) - { - String org, val; - // Jdk - org = activation.getJdk(); - val = interpolate( org ); - if ( org != val ) - { - activation.setJdk( val ); - } - // OS - visit( activation.getOs() ); - // Property - visit( activation.getProperty() ); - // File - visit( activation.getFile() ); - } - } - - private void visit( ActivationOS activationOS ) - { - if ( activationOS != null ) - { - String org, val; - // Name - org = activationOS.getName(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setName( val ); - } - // Family - org = activationOS.getFamily(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setFamily( val ); - } - // Arch - org = activationOS.getArch(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setArch( val ); - } - // Version - org = activationOS.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setVersion( val ); - } - } - } - - private void visit( ActivationProperty activationProperty ) - { - if ( activationProperty != null ) - { - String org, val; - // Name - org = activationProperty.getName(); - val = interpolate( org ); - if ( org != val ) - { - activationProperty.setName( val ); - } - // Value - org = activationProperty.getValue(); - val = interpolate( org ); - if ( org != val ) - { - activationProperty.setValue( val ); - } - } - } - - private void visit( ActivationFile activationFile ) - { - if ( activationFile != null ) - { - String org, val; - // Missing - org = activationFile.getMissing(); - val = interpolate( org ); - if ( org != val ) - { - activationFile.setMissing( val ); - } - // Exists - org = activationFile.getExists(); - val = interpolate( org ); - if ( org != val ) - { - activationFile.setExists( val ); - } - } - } - - private void visit( ModelBase modelBase ) - { - if ( modelBase != null ) - { - visit( modelBase.getModules() ); - visit( modelBase.getDistributionManagement() ); - visit( modelBase.getProperties() ); - visit( modelBase.getDependencyManagement() ); - for ( Dependency dependency : modelBase.getDependencies() ) - { - visit( dependency ); - } - for ( Repository repository : modelBase.getRepositories() ) - { - visit( repository ); - } - for ( Repository repository : modelBase.getPluginRepositories() ) - { - visit( repository ); - } - visit( modelBase.getReporting() ); - } - } - - private void visit( DistributionManagement distributionManagement ) - { - if ( distributionManagement != null ) - { - String org, val; - // Repository - visit( distributionManagement.getRepository() ); - // SnapshotRepository - visit( distributionManagement.getSnapshotRepository() ); - // Site - visit( distributionManagement.getSite() ); - // DownloadUrl - org = distributionManagement.getDownloadUrl(); - val = interpolate( org ); - if ( org != val ) - { - distributionManagement.setDownloadUrl( val ); - } - // Relocation - visit( distributionManagement.getRelocation() ); - } - } - - private void visit( Site site ) - { - if ( site != null ) - { - String org, val; - // Id - org = site.getId(); - val = interpolate( org ); - if ( org != val ) - { - site.setId( val ); - } - // Name - org = site.getName(); - val = interpolate( org ); - if ( org != val ) - { - site.setName( val ); - } - // Url - org = site.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - site.setUrl( val ); - } - // ChildSiteUrlInheritAppendPath - org = site.getChildSiteUrlInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - site.setChildSiteUrlInheritAppendPath( val ); - } - } - } - - private void visit( Relocation relocation ) - { - if ( relocation != null ) - { - String org, val; - // GroupId - org = relocation.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setGroupId( val ); - } - // ArtifactId - org = relocation.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setArtifactId( val ); - } - // Version - org = relocation.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setVersion( val ); - } - // Message - org = relocation.getMessage(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setMessage( val ); - } - } - } - - private void visit( DependencyManagement dependencyManagement ) - { - if ( dependencyManagement != null ) - { - // Dependencies - for ( Dependency dependency : dependencyManagement.getDependencies() ) - { - visit( dependency ); - } - } - } - - private void visit( Repository repository ) - { - if ( repository != null ) - { - visit( (RepositoryBase) repository ); - visit( repository.getReleases() ); - visit( repository.getSnapshots() ); - } - } - - private void visit( RepositoryBase repositoryBase ) - { - if ( repositoryBase != null ) - { - // Id - String orgId = repositoryBase.getId(); - String intId = interpolate( orgId ); - if ( orgId != intId ) - { - repositoryBase.setId( intId ); - } - // Name - String orgName = repositoryBase.getName(); - String intName = interpolate( orgName ); - if ( orgName != intName ) - { - repositoryBase.setName( intName ); - } - // Url - String orgUrl = repositoryBase.getUrl(); - String intUrl = interpolate( orgUrl ); - if ( orgUrl != intUrl ) - { - repositoryBase.setUrl( intUrl ); - } - // Layout - String orgLayout = repositoryBase.getLayout(); - String intLayout = interpolate( orgLayout ); - if ( orgLayout != intLayout ) - { - repositoryBase.setLayout( intLayout ); - } - } - } - - private void visit( RepositoryPolicy repositoryPolicy ) - { - if ( repositoryPolicy != null ) - { - // Enabled - String orgEnabled = repositoryPolicy.getEnabled(); - String intEnabled = interpolate( orgEnabled ); - if ( orgEnabled != intEnabled ) - { - repositoryPolicy.setEnabled( intEnabled ); - } - // UpdatePolicy - String orgUpdatePolicy = repositoryPolicy.getUpdatePolicy(); - String intUpdatePolicy = interpolate( orgUpdatePolicy ); - if ( orgUpdatePolicy != intUpdatePolicy ) - { - repositoryPolicy.setUpdatePolicy( intUpdatePolicy ); - } - // ChecksumPolicy - String orgChecksumPolicy = repositoryPolicy.getChecksumPolicy(); - String intChecksumPolicy = interpolate( orgChecksumPolicy ); - if ( orgChecksumPolicy != intChecksumPolicy ) - { - repositoryPolicy.setChecksumPolicy( intChecksumPolicy ); - } - } - } - - private void visit( Dependency dependency ) - { - if ( dependency != null ) - { - String org, val; - // GroupId - org = dependency.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setGroupId( val ); - dependency.clearManagementKey(); - } - // ArtifactId - org = dependency.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setArtifactId( val ); - dependency.clearManagementKey(); - } - // Version - org = dependency.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setVersion( val ); - } - // Type - org = dependency.getType(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setType( val ); - dependency.clearManagementKey(); - } - // Classifier - org = dependency.getClassifier(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setClassifier( val ); - dependency.clearManagementKey(); - } - // Scope - org = dependency.getScope(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setScope( val ); - } - // SystemPath - org = dependency.getSystemPath(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setSystemPath( val ); - } - // Exclusions - for ( Exclusion exclusion : dependency.getExclusions() ) - { - visit( exclusion ); - } - // Optional - org = dependency.getOptional(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setOptional( val ); - } - } - } - - private void visit( Exclusion exclusion ) - { - if ( exclusion != null ) - { - String org, val; - // GroupId - org = exclusion.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - exclusion.setGroupId( val ); - } - // ArtifactId - org = exclusion.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - exclusion.setArtifactId( val ); - } - } - } - - private void visit( Reporting reporting ) - { - if ( reporting != null ) - { - String org, val; - // ExcludeDefaults - org = reporting.getExcludeDefaults(); - val = interpolate( org ); - if ( org != val ) - { - reporting.setExcludeDefaults( val ); - } - // OutputDirectory - org = reporting.getOutputDirectory(); - val = interpolate( org ); - if ( org != val ) - { - reporting.setOutputDirectory( val ); - } - // Plugins - for ( ReportPlugin plugin : reporting.getPlugins() ) - { - visit( plugin ); - } - } - } - - private void visit( ReportPlugin plugin ) - { - if ( plugin != null ) - { - String org, val; - // Inherited - org = plugin.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) plugin.getConfiguration() ); - // GroupId - org = plugin.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setGroupId( val ); - } - // ArtifactId - org = plugin.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setArtifactId( val ); - } - // Version - org = plugin.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setVersion( val ); - } - // ReportSets - for ( ReportSet reportSet : plugin.getReportSets() ) - { - visit( reportSet ); - } - } - } - - private void visit( ReportSet reportSet ) - { - if ( reportSet != null ) - { - String org, val; - // Inherited - org = reportSet.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - reportSet.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) reportSet.getConfiguration() ); - // Id - org = reportSet.getId(); - val = interpolate( org ); - if ( org != val ) - { - reportSet.setId( val ); - } - // Reports - visit( reportSet.getReports() ); - } - } - - private void visit( Properties properties ) - { - if ( properties != null ) - { - for ( Map.Entry entry : properties.entrySet() ) - { - Object v = entry.getValue(); - if ( v instanceof String ) - { - String value = (String) v; - String inter = interpolate( value ); - if ( value != inter && inter != null ) - { - entry.setValue( inter ); - } - } - } - } - } - - private void visit( List list ) - { - if ( list != null ) - { - ListIterator it = list.listIterator(); - while ( it.hasNext() ) - { - String value = it.next(); - String inter = interpolate( value ); - if ( value != inter ) - { - it.set( inter ); - } - } - } - } - - private String interpolate( String value ) - { - return interpolator.interpolate( value ); - } - - } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java index 3501df9760e6..568dfac197a3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java @@ -23,8 +23,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.file.Path; import java.util.Map; import java.util.Objects; @@ -33,12 +31,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelSourceTransformer; import org.apache.maven.model.building.TransformerContext; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.apache.maven.model.io.xpp3.MavenXpp3ReaderEx; +import org.apache.maven.model.v4.MavenXpp3Reader; +import org.apache.maven.model.v4.MavenXpp3ReaderEx; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.XmlStreamReader; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; @@ -58,10 +56,6 @@ public class DefaultModelReader { private final ModelSourceTransformer transformer; - private Method readMethod; - - private Method readMethodEx; - @Inject public DefaultModelReader( ModelSourceTransformer transformer ) { @@ -78,9 +72,7 @@ public Model read( File input, Map options ) { Model model = read( in, input.toPath(), options ); - model.setPomFile( input ); - - return model; + return model.withPomFile( input.toPath() ); } } @@ -117,6 +109,11 @@ private boolean isStrict( Map options ) private InputSource getSource( Map options ) { Object value = ( options != null ) ? options.get( INPUT_SOURCE ) : null; + if ( value instanceof org.apache.maven.model.InputSource ) + { + org.apache.maven.model.InputSource src = ( org.apache.maven.model.InputSource ) value; + return new InputSource( src.getModelId(), src.getLocation() ); + } return (InputSource) value; } @@ -140,25 +137,13 @@ private Model read( Reader reader, Path pomFile, Map options ) InputSource source = getSource( options ); boolean strict = isStrict( options ); - try + if ( source != null ) { - if ( source != null ) - { - return readModelEx( transformingParser, source, strict ); - } - else - { - return readModel( transformingParser, strict ); - } + return readModelEx( transformingParser, source, strict ); } - catch ( InvocationTargetException e ) + else { - Throwable cause = e.getCause(); - if ( cause instanceof Exception ) - { - throw ( Exception ) cause; - } - throw e; + return readModel( transformingParser, strict ); } } catch ( XmlPullParserException e ) @@ -176,30 +161,17 @@ private Model read( Reader reader, Path pomFile, Map options ) } private Model readModel( XmlPullParser parser, boolean strict ) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException + throws XmlPullParserException, IOException { - if ( readMethod == null ) - { - readMethod = MavenXpp3Reader.class.getDeclaredMethod( "read", XmlPullParser.class, boolean.class ); - readMethod.setAccessible( true ); - } MavenXpp3Reader mr = new MavenXpp3Reader(); - Object model = readMethod.invoke( mr, parser, strict ); - return ( Model ) model; + return mr.read( parser, strict ); } private Model readModelEx( XmlPullParser parser, InputSource source, boolean strict ) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException + throws XmlPullParserException, IOException { - if ( readMethodEx == null ) - { - readMethodEx = MavenXpp3ReaderEx.class.getDeclaredMethod( "read", - XmlPullParser.class, boolean.class, InputSource.class ); - readMethodEx.setAccessible( true ); - } MavenXpp3ReaderEx mr = new MavenXpp3ReaderEx(); - Object model = readMethodEx.invoke( mr, parser, strict, source ); - return ( Model ) model; + return mr.read( parser, strict, source ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java index a6d4d984d55e..31435693317c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java @@ -30,8 +30,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Writer; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenXpp3Writer; import org.codehaus.plexus.util.WriterFactory; /** @@ -90,4 +90,23 @@ public void write( OutputStream output, Map options, Model model } } + @Override + public void write( File output, Map options, org.apache.maven.model.Model model ) throws IOException + { + write( output, options, model.getDelegate() ); + } + + @Override + public void write( Writer output, Map options, org.apache.maven.model.Model model ) + throws IOException + { + write( output, options, model.getDelegate() ); + } + + @Override + public void write( OutputStream output, Map options, org.apache.maven.model.Model model ) + throws IOException + { + write( output, options, model.getDelegate() ); + } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java index 04b1a3017cdb..c6ab1cf71dfe 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java @@ -25,7 +25,8 @@ import java.io.Reader; import java.util.Map; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; /** * Handles deserialization of a model from some kind of textual format like XML. @@ -43,7 +44,7 @@ public interface ModelReader /** * The key for the option to enable tracking of line/column numbers. This option is of type - * {@link org.apache.maven.model.InputSource} and defaults to {@code null}. Providing an input source enables + * {@link InputSource} and defaults to {@code null}. Providing an input source enables * location tracking. */ String INPUT_SOURCE = "org.apache.maven.model.io.inputSource"; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java index af7e0cab30ae..d32c1c2cea45 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java @@ -25,7 +25,7 @@ import java.io.Writer; import java.util.Map; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Handles serialization of a model into some kind of textual format like XML. @@ -71,4 +71,40 @@ void write( Writer output, Map options, Model model ) void write( OutputStream output, Map options, Model model ) throws IOException; + /** + * Writes the supplied model to the specified file. Any non-existing parent directories of the output file will be + * created automatically. + * + * @param output The file to serialize the model to, must not be {@code null}. + * @param options The options to use for serialization, may be {@code null} to use the default values. + * @param model The model to serialize, must not be {@code null}. + * @throws IOException If the model could not be serialized. + */ + void write( File output, Map options, org.apache.maven.model.Model model ) + throws IOException; + + /** + * Writes the supplied model to the specified character writer. The writer will be automatically closed before the + * method returns. + * + * @param output The writer to serialize the model to, must not be {@code null}. + * @param options The options to use for serialization, may be {@code null} to use the default values. + * @param model The model to serialize, must not be {@code null}. + * @throws IOException If the model could not be serialized. + */ + void write( Writer output, Map options, org.apache.maven.model.Model model ) + throws IOException; + + /** + * Writes the supplied model to the specified byte stream. The stream will be automatically closed before the method + * returns. + * + * @param output The stream to serialize the model to, must not be {@code null}. + * @param options The options to use for serialization, may be {@code null} to use the default values. + * @param model The model to serialize, must not be {@code null}. + * @throws IOException If the model could not be serialized. + */ + void write( OutputStream output, Map options, org.apache.maven.model.Model model ) + throws IOException; + } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java index 499f3558a0d3..17c0b236a445 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java @@ -19,6 +19,7 @@ * under the License. */ +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -27,10 +28,10 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -50,9 +51,10 @@ public class DefaultDependencyManagementInjector private ManagementModelMerger merger = new ManagementModelMerger(); @Override - public void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectManagement( org.apache.maven.model.Model model, ModelBuildingRequest request, + ModelProblemCollector problems ) { - merger.mergeManagedDependencies( model ); + model.update( merger.mergeManagedDependencies( model.getDelegate() ) ); } /** @@ -62,7 +64,7 @@ protected static class ManagementModelMerger extends MavenModelMerger { - public void mergeManagedDependencies( Model model ) + public Model mergeManagedDependencies( Model model ) { DependencyManagement dependencyManagement = model.getDependencyManagement(); if ( dependencyManagement != null ) @@ -76,39 +78,55 @@ public void mergeManagedDependencies( Model model ) dependencies.put( key, dependency ); } + boolean modified = false; for ( Dependency managedDependency : dependencyManagement.getDependencies() ) { Object key = getDependencyKey().apply( managedDependency ); Dependency dependency = dependencies.get( key ); if ( dependency != null ) { - mergeDependency( dependency, managedDependency, false, context ); + Dependency merged = mergeDependency( dependency, managedDependency, false, context ); + if ( merged != dependency ) + { + dependencies.put( key, merged ); + modified = true; + } } } + + if ( modified ) + { + List newDeps = new ArrayList<>( dependencies.size() ); + for ( Dependency dep : model.getDependencies() ) + { + Object key = getDependencyKey().apply( dep ); + Dependency dependency = dependencies.get( key ); + newDeps.add( dependency ); + } + return Model.newBuilder( model ).dependencies( newDeps ).build(); + } } + return model; } @Override - protected void mergeDependency_Optional( Dependency target, Dependency source, boolean sourceDominant, + protected void mergeDependency_Optional( Dependency.Builder builder, + Dependency target, Dependency source, boolean sourceDominant, Map context ) { // optional flag is not managed } @Override - protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, + protected void mergeDependency_Exclusions( Dependency.Builder builder, + Dependency target, Dependency source, boolean sourceDominant, Map context ) { List tgt = target.getExclusions(); if ( tgt.isEmpty() ) { List src = source.getExclusions(); - - for ( Exclusion element : src ) - { - Exclusion clone = element.clone(); - target.addExclusion( clone ); - } + builder.exclusions( src ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java index 752b976d04ad..0b21a3b7c2dc 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java @@ -28,12 +28,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -53,9 +53,10 @@ public class DefaultPluginManagementInjector private ManagementModelMerger merger = new ManagementModelMerger(); @Override - public void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectManagement( org.apache.maven.model.Model model, ModelBuildingRequest request, + ModelProblemCollector problems ) { - merger.mergeManagedBuildPlugins( model ); + model.update( merger.mergeManagedBuildPlugins( model.getDelegate() ) ); } /** @@ -65,7 +66,7 @@ protected static class ManagementModelMerger extends MavenModelMerger { - public void mergeManagedBuildPlugins( Model model ) + public Model mergeManagedBuildPlugins( Model model ) { Build build = model.getBuild(); if ( build != null ) @@ -73,18 +74,17 @@ public void mergeManagedBuildPlugins( Model model ) PluginManagement pluginManagement = build.getPluginManagement(); if ( pluginManagement != null ) { - mergePluginContainerPlugins( build, pluginManagement ); + return model.withBuild( mergePluginContainerPlugins( build, pluginManagement ) ); } } + return model; } - private void mergePluginContainerPlugins( PluginContainer target, PluginContainer source ) + private Build mergePluginContainerPlugins( Build target, PluginContainer source ) { List src = source.getPlugins(); if ( !src.isEmpty() ) { - List tgt = target.getPlugins(); - Map managedPlugins = new LinkedHashMap<>( src.size() * 2 ); Map context = Collections.emptyMap(); @@ -95,21 +95,25 @@ private void mergePluginContainerPlugins( PluginContainer target, PluginContaine managedPlugins.put( key, element ); } - for ( Plugin element : tgt ) + List newPlugins = new ArrayList<>(); + for ( Plugin element : target.getPlugins() ) { Object key = getPluginKey().apply( element ); Plugin managedPlugin = managedPlugins.get( key ); if ( managedPlugin != null ) { - mergePlugin( element, managedPlugin, false, context ); + element = mergePlugin( element, managedPlugin, false, context ); } + newPlugins.add( element ); } + return target.withPlugins( newPlugins ); } + return target; } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) + protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source, + boolean sourceDominant, Map context ) { List src = source.getExecutions(); if ( !src.isEmpty() ) @@ -122,7 +126,7 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou for ( PluginExecution element : src ) { Object key = getPluginExecutionKey().apply( element ); - merged.put( key, element.clone() ); + merged.put( key, element ); } for ( PluginExecution element : tgt ) @@ -131,12 +135,12 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou PluginExecution existing = merged.get( key ); if ( existing != null ) { - mergePluginExecution( element, existing, sourceDominant, context ); + element = mergePluginExecution( element, existing, sourceDominant, context ); } merged.put( key, element ); } - target.setExecutions( new ArrayList<>( merged.values() ) ); + builder.executions( merged.values() ); } } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java b/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java index 049ce1f1286b..59c57cefa450 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java @@ -26,26 +26,27 @@ import java.util.Map; import java.util.Set; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DeploymentRepository; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Extension; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryBase; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.CiManagement; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DeploymentRepository; +import org.apache.maven.api.model.DistributionManagement; +import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.Extension; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.IssueManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Organization; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.ReportSet; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.model.RepositoryBase; +import org.apache.maven.api.model.Scm; +import org.apache.maven.api.model.Site; +import org.apache.maven.model.v4.MavenMerger; import org.codehaus.plexus.util.StringUtils; /** @@ -55,7 +56,7 @@ * @author Benjamin Bentmann */ public class MavenModelMerger - extends ModelMerger + extends MavenMerger { /** @@ -69,42 +70,44 @@ public class MavenModelMerger public static final String ARTIFACT_ID = "artifact-id"; @Override - protected void mergeModel( Model target, Model source, boolean sourceDominant, Map context ) + protected Model mergeModel( Model target, Model source, boolean sourceDominant, Map context ) { context.put( ARTIFACT_ID, target.getArtifactId() ); - super.mergeModel( target, source, sourceDominant, context ); + return super.mergeModel( target, source, sourceDominant, context ); } @Override - protected void mergeModel_Name( Model target, Model source, boolean sourceDominant, Map context ) + protected void mergeModel_Name( Model.Builder builder, Model target, Model source, + boolean sourceDominant, Map context ) { String src = source.getName(); if ( src != null ) { if ( sourceDominant ) { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); + builder.name( src ); + builder.location( "name", source.getLocation( "name" ) ); } } } @Override - protected void mergeModel_Url( Model target, Model source, boolean sourceDominant, Map context ) + protected void mergeModel_Url( Model.Builder builder, Model target, Model source, + boolean sourceDominant, Map context ) { String src = source.getUrl(); if ( src != null ) { if ( sourceDominant ) { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( src ); + builder.location( "url", source.getLocation( "url" ) ); } else if ( target.getUrl() == null ) { - target.setUrl( extrapolateChildUrl( src, source.isChildProjectUrlInheritAppendPath(), context ) ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( extrapolateChildUrl( src, source.isChildProjectUrlInheritAppendPath(), context ) ); + builder.location( "url", source.getLocation( "url" ) ); } } } @@ -114,7 +117,7 @@ else if ( target.getUrl() == null ) * merger */ @Override - protected void mergeModel_Organization( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Organization( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { Organization src = source.getOrganization(); @@ -123,17 +126,15 @@ protected void mergeModel_Organization( Model target, Model source, boolean sour Organization tgt = target.getOrganization(); if ( tgt == null ) { - tgt = new Organization(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setOrganization( tgt ); - mergeOrganization( tgt, src, sourceDominant, context ); + builder.organization( src ); + builder.location( "organisation", source.getLocation( "organisation" ) ); } } } @Override - protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant, - Map context ) + protected void mergeModel_IssueManagement( Model.Builder builder, Model target, Model source, + boolean sourceDominant, Map context ) { IssueManagement src = source.getIssueManagement(); if ( src != null ) @@ -141,16 +142,14 @@ protected void mergeModel_IssueManagement( Model target, Model source, boolean s IssueManagement tgt = target.getIssueManagement(); if ( tgt == null ) { - tgt = new IssueManagement(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setIssueManagement( tgt ); - mergeIssueManagement( tgt, src, sourceDominant, context ); + builder.issueManagement( src ); + builder.location( "issueManagement", source.getLocation( "issueManagement" ) ); } } } @Override - protected void mergeModel_CiManagement( Model target, Model source, boolean sourceDominant, + protected void mergeModel_CiManagement( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { CiManagement src = source.getCiManagement(); @@ -159,85 +158,75 @@ protected void mergeModel_CiManagement( Model target, Model source, boolean sour CiManagement tgt = target.getCiManagement(); if ( tgt == null ) { - tgt = new CiManagement(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setCiManagement( tgt ); - mergeCiManagement( tgt, src, sourceDominant, context ); + builder.ciManagement( src ); + builder.location( "ciManagement", source.getLocation( "ciManagement" ) ); } } } @Override - protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant, + protected void mergeModel_ModelVersion( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant, + protected void mergeModel_ArtifactId( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Profiles( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Prerequisites( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Licenses( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { - if ( target.getLicenses().isEmpty() ) - { - target.setLicenses( new ArrayList<>( source.getLicenses() ) ); - } + builder.licenses( target.getLicenses().isEmpty() ? source.getLicenses() : target.getLicenses() ); } @Override - protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Developers( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { - if ( target.getDevelopers().isEmpty() ) - { - target.setDevelopers( new ArrayList<>( source.getDevelopers() ) ); - } + builder.developers( target.getDevelopers().isEmpty() ? source.getDevelopers() : target.getDevelopers() ); } @Override - protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Contributors( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { - if ( target.getContributors().isEmpty() ) - { - target.setContributors( new ArrayList<>( source.getContributors() ) ); - } + builder.contributors( target.getContributors().isEmpty() + ? source.getContributors() : target.getContributors() ); } @Override - protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant, + protected void mergeModel_MailingLists( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { if ( target.getMailingLists().isEmpty() ) { - target.setMailingLists( new ArrayList<>( source.getMailingLists() ) ); + builder.mailingLists( source.getMailingLists() ); } } @Override - protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) + protected void mergeModelBase_Modules( ModelBase.Builder builder, ModelBase target, ModelBase source, + boolean sourceDominant, Map context ) { List src = source.getModules(); if ( !src.isEmpty() && sourceDominant ) @@ -260,8 +249,8 @@ protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boole indices.add( ~i ); } } - target.setModules( merged ); - target.setLocation( "modules", InputLocation.merge( target.getLocation( "modules" ), + builder.modules( merged ); + builder.location( "modules", InputLocation.merge( target.getLocation( "modules" ), source.getLocation( "modules" ), indices ) ); } } @@ -271,8 +260,8 @@ protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boole * source-first, dominant-first, recessive-first */ @Override - protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) + protected void mergeModelBase_Repositories( ModelBase.Builder builder, ModelBase target, ModelBase source, + boolean sourceDominant, Map context ) { List src = source.getRepositories(); if ( !src.isEmpty() ) @@ -307,13 +296,13 @@ protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, } } - target.setRepositories( new ArrayList<>( merged.values() ) ); + builder.repositories( merged.values() ); } } @Override - protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) + protected void mergeModelBase_PluginRepositories( ModelBase.Builder builder, ModelBase target, ModelBase source, + boolean sourceDominant, Map context ) { List src = source.getPluginRepositories(); if ( !src.isEmpty() ) @@ -348,7 +337,7 @@ protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase so } } - target.setPluginRepositories( new ArrayList<>( merged.values() ) ); + builder.pluginRepositories( merged.values() ); } } @@ -356,8 +345,8 @@ protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase so * TODO: Whether duplicates should be removed looks like an option for the generated merger. */ @Override - protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) + protected void mergeBuildBase_Filters( BuildBase.Builder builder, BuildBase target, BuildBase source, + boolean sourceDominant, Map context ) { List src = source.getFilters(); if ( !src.isEmpty() ) @@ -373,33 +362,48 @@ protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boole merged.add( s ); } } - target.setFilters( merged ); + builder.filters( merged ); } } @Override - protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) + protected void mergeBuildBase_Resources( BuildBase.Builder builder, BuildBase target, BuildBase source, + boolean sourceDominant, Map context ) { if ( sourceDominant || target.getResources().isEmpty() ) { - super.mergeBuildBase_Resources( target, source, sourceDominant, context ); + super.mergeBuildBase_Resources( builder, target, source, sourceDominant, context ); } } @Override - protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant, + protected void mergeBuildBase_TestResources( BuildBase.Builder builder, + BuildBase target, + BuildBase source, + boolean sourceDominant, Map context ) { if ( sourceDominant || target.getTestResources().isEmpty() ) { - super.mergeBuildBase_TestResources( target, source, sourceDominant, context ); + super.mergeBuildBase_TestResources( builder, target, source, sourceDominant, context ); } } @Override - protected void mergeDistributionManagement_Repository( DistributionManagement target, - DistributionManagement source, boolean sourceDominant, + protected void mergeDistributionManagement_Relocation( DistributionManagement.Builder builder, + DistributionManagement target, + DistributionManagement source, + boolean sourceDominant, + Map context ) + { + } + + + @Override + protected void mergeDistributionManagement_Repository( DistributionManagement.Builder builder, + DistributionManagement target, + DistributionManagement source, + boolean sourceDominant, Map context ) { DeploymentRepository src = source.getRepository(); @@ -408,16 +412,15 @@ protected void mergeDistributionManagement_Repository( DistributionManagement ta DeploymentRepository tgt = target.getRepository(); if ( sourceDominant || tgt == null ) { - tgt = new DeploymentRepository(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setRepository( tgt ); - mergeDeploymentRepository( tgt, src, sourceDominant, context ); + tgt = DeploymentRepository.newInstance( false ); + builder.repository( mergeDeploymentRepository( tgt, src, sourceDominant, context ) ); } } } @Override - protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target, + protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement.Builder builder, + DistributionManagement target, DistributionManagement source, boolean sourceDominant, Map context ) @@ -428,42 +431,41 @@ protected void mergeDistributionManagement_SnapshotRepository( DistributionManag DeploymentRepository tgt = target.getSnapshotRepository(); if ( sourceDominant || tgt == null ) { - tgt = new DeploymentRepository(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setSnapshotRepository( tgt ); - mergeDeploymentRepository( tgt, src, sourceDominant, context ); + tgt = DeploymentRepository.newInstance( false ); + builder.snapshotRepository( mergeDeploymentRepository( tgt, src, sourceDominant, context ) ); } } } @Override - protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) + protected void mergeDistributionManagement_Site( DistributionManagement.Builder builder, + DistributionManagement target, + DistributionManagement source, + boolean sourceDominant, + Map context ) { Site src = source.getSite(); if ( src != null ) { Site tgt = target.getSite(); + if ( tgt == null ) + { + tgt = Site.newBuilder( false ).build(); + } + Site.Builder sbuilder = Site.newBuilder( tgt ); if ( sourceDominant || tgt == null || isSiteEmpty( tgt ) ) { - if ( tgt == null ) - { - tgt = new Site(); - } - tgt.setLocation( "", src.getLocation( "" ) ); - target.setSite( tgt ); - mergeSite( tgt, src, sourceDominant, context ); + mergeSite( sbuilder, tgt, src, sourceDominant, context ); } - mergeSite_ChildSiteUrlInheritAppendPath( tgt, src, sourceDominant, context ); + super.mergeSite_ChildSiteUrlInheritAppendPath( sbuilder, tgt, src, sourceDominant, context ); + builder.site( sbuilder.build() ); } } @Override - protected void mergeSite( Site target, Site source, boolean sourceDominant, Map context ) + protected void mergeSite_ChildSiteUrlInheritAppendPath( Site.Builder builder, Site target, Site source, + boolean sourceDominant, Map context ) { - mergeSite_Id( target, source, sourceDominant, context ); - mergeSite_Name( target, source, sourceDominant, context ); - mergeSite_Url( target, source, sourceDominant, context ); } protected boolean isSiteEmpty( Site site ) @@ -473,87 +475,90 @@ protected boolean isSiteEmpty( Site site ) } @Override - protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map context ) + protected void mergeSite_Url( Site.Builder builder, Site target, Site source, + boolean sourceDominant, Map context ) { String src = source.getUrl(); if ( src != null ) { if ( sourceDominant ) { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( src ); + builder.location( "url", source.getLocation( "url" ) ); } else if ( target.getUrl() == null ) { - target.setUrl( extrapolateChildUrl( src, source.isChildSiteUrlInheritAppendPath(), context ) ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( extrapolateChildUrl( src, source.isChildSiteUrlInheritAppendPath(), context ) ); + builder.location( "url", source.getLocation( "url" ) ); } } } @Override - protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map context ) + protected void mergeScm_Url( Scm.Builder builder, Scm target, Scm source, + boolean sourceDominant, Map context ) { String src = source.getUrl(); if ( src != null ) { if ( sourceDominant ) { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( src ); + builder.location( "url", source.getLocation( "url" ) ); } else if ( target.getUrl() == null ) { - target.setUrl( extrapolateChildUrl( src, source.isChildScmUrlInheritAppendPath(), context ) ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( extrapolateChildUrl( src, source.isChildScmUrlInheritAppendPath(), context ) ); + builder.location( "url", source.getLocation( "url" ) ); } } } @Override - protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map context ) + protected void mergeScm_Connection( Scm.Builder builder, Scm target, Scm source, + boolean sourceDominant, Map context ) { String src = source.getConnection(); if ( src != null ) { if ( sourceDominant ) { - target.setConnection( src ); - target.setLocation( "connection", source.getLocation( "connection" ) ); + builder.connection( src ); + builder.location( "connection", source.getLocation( "connection" ) ); } else if ( target.getConnection() == null ) { - target.setConnection( extrapolateChildUrl( src, source.isChildScmConnectionInheritAppendPath(), + builder.connection( extrapolateChildUrl( src, source.isChildScmConnectionInheritAppendPath(), context ) ); - target.setLocation( "connection", source.getLocation( "connection" ) ); + builder.location( "connection", source.getLocation( "connection" ) ); } } } @Override - protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant, - Map context ) + protected void mergeScm_DeveloperConnection( Scm.Builder builder, Scm target, Scm source, + boolean sourceDominant, Map context ) { String src = source.getDeveloperConnection(); if ( src != null ) { if ( sourceDominant ) { - target.setDeveloperConnection( src ); - target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) ); + builder.developerConnection( src ); + builder.location( "developerConnection", source.getLocation( "developerConnection" ) ); } else if ( target.getDeveloperConnection() == null ) { String e = extrapolateChildUrl( src, source.isChildScmDeveloperConnectionInheritAppendPath(), context ); - target.setDeveloperConnection( e ); - target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) ); + builder.developerConnection( e ); + builder.location( "developerConnection", source.getLocation( "developerConnection" ) ); } } } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) + protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source, + boolean sourceDominant, Map context ) { List src = source.getExecutions(); if ( !src.isEmpty() ) @@ -578,17 +583,18 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou PluginExecution existing = merged.get( key ); if ( existing != null ) { - mergePluginExecution( element, existing, sourceDominant, context ); + element = mergePluginExecution( element, existing, sourceDominant, context ); } merged.put( key, element ); } - target.setExecutions( new ArrayList<>( merged.values() ) ); + builder.executions( merged.values() ); } } @Override - protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant, + protected void mergePluginExecution_Goals( PluginExecution.Builder builder, PluginExecution target, + PluginExecution source, boolean sourceDominant, Map context ) { List src = source.getGoals(); @@ -605,12 +611,13 @@ protected void mergePluginExecution_Goals( PluginExecution target, PluginExecuti merged.add( s ); } } - target.setGoals( merged ); + builder.goals( merged ); } } @Override - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, + protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, ReportPlugin target, + ReportPlugin source, boolean sourceDominant, Map context ) { List src = source.getReportSets(); @@ -639,7 +646,7 @@ protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin s merged.put( key, element ); } - target.setReportSets( new ArrayList<>( merged.values() ) ); + builder.reportSets( merged.values() ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java index 9f86c0997eac..c56287c92fad 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java @@ -24,14 +24,15 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -51,8 +52,10 @@ public class DefaultModelNormalizer private DuplicateMerger merger = new DuplicateMerger(); @Override - public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { + Model.Builder builder = Model.newBuilder( model ); + Build build = model.getBuild(); if ( build != null ) { @@ -65,14 +68,16 @@ public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelPro Plugin first = normalized.get( key ); if ( first != null ) { - merger.mergePlugin( plugin, first ); + plugin = merger.mergePlugin( plugin, first ); } normalized.put( key, plugin ); } if ( plugins.size() != normalized.size() ) { - build.setPlugins( new ArrayList<>( normalized.values() ) ); + builder.build( Build.newBuilder( build ) + .plugins( normalized.values() ) + .build() ); } } @@ -93,8 +98,10 @@ public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelPro if ( dependencies.size() != normalized.size() ) { - model.setDependencies( new ArrayList<>( normalized.values() ) ); + builder.dependencies( normalized.values() ); } + + return builder.build(); } /** @@ -104,38 +111,64 @@ protected static class DuplicateMerger extends MavenModelMerger { - public void mergePlugin( Plugin target, Plugin source ) + public Plugin mergePlugin( Plugin target, Plugin source ) { - super.mergePlugin( target, source, false, Collections.emptyMap() ); + return super.mergePlugin( target, source, false, Collections.emptyMap() ); } } @Override - public void injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { - injectDependencyDefaults( model.getDependencies() ); + Model.Builder builder = Model.newBuilder( model ); + builder.dependencies( injectList( model.getDependencies(), this::injectDependency ) ); Build build = model.getBuild(); if ( build != null ) { - for ( Plugin plugin : build.getPlugins() ) - { - injectDependencyDefaults( plugin.getDependencies() ); - } + Build newBuild = Build.newBuilder( build ) + .plugins( injectList( build.getPlugins(), this::injectPlugin ) ) + .build(); + builder.build( newBuild != build ? newBuild : null ); } + + return builder.build(); } - private void injectDependencyDefaults( List dependencies ) + private Plugin injectPlugin( Plugin p ) { - for ( Dependency dependency : dependencies ) + return Plugin.newBuilder( p ) + .dependencies( injectList( p.getDependencies(), this::injectDependency ) ) + .build(); + } + + private Dependency injectDependency( Dependency d ) + { + // we cannot set this directly in the MDO due to the interactions with dependency management + return StringUtils.isEmpty( d.getScope() ) ? Dependency.newBuilder( d ).scope( "compile" ).build() : d; + } + + /** + * Returns a list suited for the builders, i.e. null if not modified + */ + private List injectList( List list, Function modifer ) + { + List newList = null; + for ( int i = 0; i < list.size(); i++ ) { - if ( StringUtils.isEmpty( dependency.getScope() ) ) + T oldT = list.get( i ); + T newT = modifer.apply( oldT ); + if ( newT != oldT ) { - // we cannot set this directly in the MDO due to the interactions with dependency management - dependency.setScope( "compile" ); + if ( newList == null ) + { + newList = new ArrayList<>( list ); + } + newList.set( i, newT ); } - } + } + return newList; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java index 7cab86b65cc3..ff73a55ef92a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -39,7 +39,7 @@ public interface ModelNormalizer * @param request The model building request that holds further settings, must not be {@code null}. * @param problems The container used to collect problems that were encountered, must not be {@code null}. */ - void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); /** * Sets default values in the specified model that for technical reasons cannot be set directly in the Modello @@ -49,6 +49,6 @@ public interface ModelNormalizer * @param request The model building request that holds further settings, must not be {@code null}. * @param problems The container used to collect problems that were encountered, must not be {@code null}. */ - void injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java index 801499f6cace..2afe21f51b9a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java @@ -22,15 +22,17 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.function.Function; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Resource; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Reporting; +import org.apache.maven.api.model.Resource; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -53,61 +55,87 @@ public DefaultModelPathTranslator( PathTranslator pathTranslator ) } @Override - public void alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ) + public void alignToBaseDirectory( org.apache.maven.model.Model modelV3, File basedir, ModelBuildingRequest request ) { - if ( model == null || basedir == null ) + if ( modelV3 == null || basedir == null ) { return; } + Model model = modelV3.getDelegate(); Build build = model.getBuild(); - + Build newBuild = null; if ( build != null ) { - build.setDirectory( alignToBaseDirectory( build.getDirectory(), basedir ) ); - - build.setSourceDirectory( alignToBaseDirectory( build.getSourceDirectory(), basedir ) ); - - build.setTestSourceDirectory( alignToBaseDirectory( build.getTestSourceDirectory(), basedir ) ); - - build.setScriptSourceDirectory( alignToBaseDirectory( build.getScriptSourceDirectory(), basedir ) ); - - for ( Resource resource : build.getResources() ) - { - resource.setDirectory( alignToBaseDirectory( resource.getDirectory(), basedir ) ); - } + newBuild = Build.newBuilder( build ) + .directory( alignToBaseDirectory( build.getDirectory(), basedir ) ) + .sourceDirectory( alignToBaseDirectory( build.getSourceDirectory(), basedir ) ) + .testSourceDirectory( alignToBaseDirectory( build.getTestSourceDirectory(), basedir ) ) + .scriptSourceDirectory( alignToBaseDirectory( build.getScriptSourceDirectory(), basedir ) ) + .resources( map( build.getResources(), r -> alignToBaseDirectory( r, basedir ) ) ) + .testResources( map( build.getTestResources(), r -> alignToBaseDirectory( r, basedir ) ) ) + .filters( map( build.getFilters(), s -> alignToBaseDirectory( s, basedir ) ) ) + .outputDirectory( alignToBaseDirectory( build.getOutputDirectory(), basedir ) ) + .testOutputDirectory( alignToBaseDirectory( build.getTestOutputDirectory(), basedir ) ) + .build(); + } - for ( Resource resource : build.getTestResources() ) - { - resource.setDirectory( alignToBaseDirectory( resource.getDirectory(), basedir ) ); - } + Reporting reporting = model.getReporting(); + Reporting newReporting = null; + if ( reporting != null ) + { + newReporting = Reporting.newBuilder( reporting ) + .outputDirectory( alignToBaseDirectory( reporting.getOutputDirectory(), basedir ) ) + .build(); + } + if ( newBuild != build || newReporting != reporting ) + { + modelV3.update( Model.newBuilder( model ) + .build( newBuild ) + .reporting( newReporting ) + .build() ); + } + } - if ( build.getFilters() != null ) + private List map( List resources, Function mapper ) + { + List newResources = null; + if ( resources != null ) + { + for ( int i = 0; i < resources.size(); i++ ) { - List filters = new ArrayList<>( build.getFilters().size() ); - for ( String filter : build.getFilters() ) + T resource = resources.get( i ); + T newResource = mapper.apply( resource ); + if ( newResource != null ) { - filters.add( alignToBaseDirectory( filter, basedir ) ); + if ( newResources == null ) + { + newResources = new ArrayList<>( resources ); + } + newResources.set( i, newResource ); } - build.setFilters( filters ); } - - build.setOutputDirectory( alignToBaseDirectory( build.getOutputDirectory(), basedir ) ); - - build.setTestOutputDirectory( alignToBaseDirectory( build.getTestOutputDirectory(), basedir ) ); } + return newResources; + } - Reporting reporting = model.getReporting(); - - if ( reporting != null ) + private Resource alignToBaseDirectory( Resource resource, File basedir ) + { + if ( resource != null ) { - reporting.setOutputDirectory( alignToBaseDirectory( reporting.getOutputDirectory(), basedir ) ); + String newDir = alignToBaseDirectory( resource.getDirectory(), basedir ); + if ( newDir != null ) + { + return resource.withDirectory( newDir ); + } } + return resource; } private String alignToBaseDirectory( String path, File basedir ) { - return pathTranslator.alignToBaseDirectory( path, basedir ); + String newPath = pathTranslator.alignToBaseDirectory( path, basedir ); + return Objects.equals( path, newPath ) ? null : newPath; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java index 92d7bbd3165b..b3770b3588a4 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java @@ -38,7 +38,7 @@ @Named @Singleton public class DefaultModelUrlNormalizer - implements ModelUrlNormalizer + implements ModelUrlNormalizer { private final UrlNormalizer urlNormalizer; @@ -83,4 +83,4 @@ private String normalize( String url ) return urlNormalizer.normalize( url ); } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java index 41257ac3e9d1..2560f3c9aa0e 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.ActivationFile; +import org.apache.maven.api.model.ActivationFile; import org.apache.maven.model.profile.ProfileActivationContext; import org.codehaus.plexus.interpolation.AbstractValueSource; import org.codehaus.plexus.interpolation.InterpolationException; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java index 012a6852a6b1..69d44bc192da 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java @@ -41,7 +41,7 @@ @Named @Singleton public class DefaultPluginConfigurationExpander - implements PluginConfigurationExpander + implements PluginConfigurationExpander { @Override @@ -75,7 +75,7 @@ private void expand( List plugins ) Xpp3Dom executionConfiguration = (Xpp3Dom) execution.getConfiguration(); executionConfiguration = - Xpp3Dom.mergeXpp3Dom( executionConfiguration, new Xpp3Dom( pluginConfiguration ) ); + Xpp3Dom.mergeXpp3Dom( executionConfiguration, new Xpp3Dom( pluginConfiguration ) ); execution.setConfiguration( executionConfiguration ); } @@ -83,4 +83,4 @@ private void expand( List plugins ) } } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java index b221ac23dda6..044ec351f7b8 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java @@ -38,7 +38,7 @@ @Named @Singleton public class DefaultReportConfigurationExpander - implements ReportConfigurationExpander + implements ReportConfigurationExpander { @Override @@ -65,4 +65,4 @@ public void expandPluginConfiguration( Model model, ModelBuildingRequest request } } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java index 04b414b01cb5..75a8443e2f58 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java @@ -48,12 +48,12 @@ @Named @Singleton public class DefaultReportingConverter - implements ReportingConverter + implements ReportingConverter { private final InputLocation location; { String modelId = "org.apache.maven:maven-model-builder:" - + this.getClass().getPackage().getImplementationVersion() + ":reporting-converter"; + + this.getClass().getPackage().getImplementationVersion() + ":reporting-converter"; InputSource inputSource = new InputSource(); inputSource.setModelId( modelId ); location = new InputLocation( -1, -1, inputSource ); @@ -111,7 +111,7 @@ public void convertReporting( Model model, ModelBuildingRequest request, ModelPr // in favor of classical reporting section MSITE-647 / MSITE-684 problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE ) .setMessage( "Reporting configuration should be done in section, " - + "not in maven-site-plugin as reportPlugins parameter." ) + + "not in maven-site-plugin as reportPlugins parameter." ) .setLocation( sitePlugin.getLocation( "configuration" ) ) ); return; } @@ -144,8 +144,8 @@ public void convertReporting( Model model, ModelBuildingRequest request, ModelPr reportPlugins.addChild( reportPlugin ); if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin - && "org.apache.maven.plugins".equals( plugin.getGroupId() ) - && "maven-project-info-reports-plugin".equals( plugin.getArtifactId() ) ) + && "org.apache.maven.plugins".equals( plugin.getGroupId() ) + && "maven-project-info-reports-plugin".equals( plugin.getArtifactId() ) ) { hasMavenProjectInfoReportsPlugin = true; } @@ -190,7 +190,7 @@ private Plugin findSitePlugin( Build build ) private boolean isSitePlugin( Plugin plugin ) { return "maven-site-plugin".equals( plugin.getArtifactId() ) - && "org.apache.maven.plugins".equals( plugin.getGroupId() ); + && "org.apache.maven.plugins".equals( plugin.getGroupId() ); } private Xpp3Dom convert( ReportPlugin plugin ) @@ -271,4 +271,4 @@ private Xpp3Dom newDom( String name, String value, InputLocation location ) return dom; } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java index 2f9553b81e6a..ec7eb25c763a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java @@ -19,26 +19,25 @@ * under the License. */ +import javax.inject.Named; +import javax.inject.Singleton; + import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.ReportSet; +import org.apache.maven.api.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -58,21 +57,25 @@ public class DefaultProfileInjector private ProfileModelMerger merger = new ProfileModelMerger(); @Override - public void injectProfile( Model model, Profile profile, ModelBuildingRequest request, + public void injectProfile( org.apache.maven.model.Model model, + org.apache.maven.model.Profile profile, + ModelBuildingRequest request, ModelProblemCollector problems ) { if ( profile != null ) { - merger.mergeModelBase( model, profile ); + Model.Builder builder = Model.newBuilder( model.getDelegate() ); + merger.mergeModelBase( builder, model.getDelegate(), profile.getDelegate() ); if ( profile.getBuild() != null ) { - if ( model.getBuild() == null ) - { - model.setBuild( new Build() ); - } - merger.mergeBuildBase( model.getBuild(), profile.getBuild() ); + Build build = model.getBuild() != null ? model.getBuild().getDelegate() : Build.newInstance(); + Build.Builder bbuilder = Build.newBuilder( build ); + merger.mergeBuildBase( bbuilder, build, profile.getBuild().getDelegate() ); + builder.build( bbuilder.build() ); } + + model.update( builder.build() ); } } @@ -83,19 +86,20 @@ protected static class ProfileModelMerger extends MavenModelMerger { - public void mergeModelBase( ModelBase target, ModelBase source ) + public void mergeModelBase( ModelBase.Builder builder, ModelBase target, ModelBase source ) { - mergeModelBase( target, source, true, Collections.emptyMap() ); + mergeModelBase( builder, target, source, true, Collections.emptyMap() ); } - public void mergeBuildBase( BuildBase target, BuildBase source ) + public void mergeBuildBase( BuildBase.Builder builder, BuildBase target, BuildBase source ) { - mergeBuildBase( target, source, true, Collections.emptyMap() ); + mergeBuildBase( builder, target, source, true, Collections.emptyMap() ); } @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, - boolean sourceDominant, Map context ) + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, + boolean sourceDominant, Map context ) { List src = source.getPlugins(); if ( !src.isEmpty() ) @@ -117,8 +121,8 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin existing = master.get( key ); if ( existing != null ) { - mergePlugin( existing, element, sourceDominant, context ); - + existing = mergePlugin( existing, element, sourceDominant, context ); + master.put( key, existing ); if ( !pending.isEmpty() ) { predecessors.put( key, pending ); @@ -143,13 +147,13 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta } result.addAll( pending ); - target.setPlugins( result ); + builder.plugins( result ); } } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) + protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source, + boolean sourceDominant, Map context ) { List src = source.getExecutions(); if ( !src.isEmpty() ) @@ -170,21 +174,18 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou PluginExecution existing = merged.get( key ); if ( existing != null ) { - mergePluginExecution( existing, element, sourceDominant, context ); - } - else - { - merged.put( key, element ); + element = mergePluginExecution( existing, element, sourceDominant, context ); } + merged.put( key, element ); } - target.setExecutions( new ArrayList<>( merged.values() ) ); + builder.executions( merged.values() ); } } @Override - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, - Map context ) + protected void mergeReporting_Plugins( Reporting.Builder builder, Reporting target, Reporting source, + boolean sourceDominant, Map context ) { List src = source.getPlugins(); if ( !src.isEmpty() ) @@ -203,22 +204,20 @@ protected void mergeReporting_Plugins( Reporting target, Reporting source, boole { Object key = getReportPluginKey().apply( element ); ReportPlugin existing = merged.get( key ); - if ( existing == null ) - { - merged.put( key, element ); - } - else + if ( existing != null ) { - mergeReportPlugin( existing, element, sourceDominant, context ); + element = mergeReportPlugin( existing, element, sourceDominant, context ); } + merged.put( key, element ); } - target.setPlugins( new ArrayList<>( merged.values() ) ); + builder.plugins( merged.values() ); } } @Override - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, + protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, ReportPlugin target, + ReportPlugin source, boolean sourceDominant, Map context ) { List src = source.getReportSets(); @@ -239,15 +238,12 @@ protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin s ReportSet existing = merged.get( key ); if ( existing != null ) { - mergeReportSet( existing, element, sourceDominant, context ); - } - else - { - merged.put( key, element ); + element = mergeReportSet( existing, element, sourceDominant, context ); } + merged.put( key, element ); } - target.setReportSets( new ArrayList<>( merged.values() ) ); + builder.reportSets( merged.values() ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java index 303aff08cff5..7ae76ad2a9ef 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Repository; /** * Signals an error when adding a repository to the model resolver. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java index a07eaf6a44d8..b3139c58c51d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java @@ -19,9 +19,11 @@ * under the License. */ -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.building.ModelSource; /** @@ -64,7 +66,7 @@ ModelSource resolveModel( String groupId, String artifactId, String version ) * * @see Parent#clone() */ - ModelSource resolveModel( Parent parent ) + ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException; /** @@ -85,7 +87,7 @@ ModelSource resolveModel( Parent parent ) * * @see Dependency#clone() */ - ModelSource resolveModel( Dependency dependency ) + ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException; /** @@ -96,7 +98,7 @@ ModelSource resolveModel( Dependency dependency ) * @param repository The repository to add to the internal search chain, must not be {@code null}. * @throws InvalidRepositoryException If the repository could not be added (e.g. due to invalid URL or layout). */ - void addRepository( Repository repository ) + void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException; /** @@ -110,7 +112,7 @@ void addRepository( Repository repository ) * @param repository The repository to add to the internal search chain, must not be {@code null}. * @throws InvalidRepositoryException If the repository could not be added (e.g. due to invalid URL or layout). */ - void addRepository( Repository repository, boolean replace ) + void addRepository( org.apache.maven.model.Repository repository, boolean replace ) throws InvalidRepositoryException; /** @@ -122,4 +124,39 @@ void addRepository( Repository repository, boolean replace ) */ ModelResolver newCopy(); + default ModelSource resolveModel( Parent parent, AtomicReference modified ) + throws UnresolvableModelException + { + org.apache.maven.model.Parent p = new org.apache.maven.model.Parent( parent ); + ModelSource result = resolveModel( p ); + if ( p.getDelegate() != parent ) + { + modified.set( p.getDelegate() ); + } + return result; + } + + default ModelSource resolveModel( Dependency dependency, AtomicReference modified ) + throws UnresolvableModelException + { + org.apache.maven.model.Dependency d = new org.apache.maven.model.Dependency( dependency ); + ModelSource result = resolveModel( d ); + if ( d.getDelegate() != dependency ) + { + modified.set( d.getDelegate() ); + } + return result; + } + + default void addRepository( Repository repository ) + throws InvalidRepositoryException + { + addRepository( new org.apache.maven.model.Repository( repository ) ); + } + + default void addRepository( Repository repository, boolean replace ) + throws InvalidRepositoryException + { + addRepository( new org.apache.maven.model.Repository( repository ), replace ); + } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java index 31df92fad022..bb6a82025677 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java @@ -28,8 +28,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelProcessor; /** @@ -78,9 +78,8 @@ public Model getSuperModel( String version ) String modelId = "org.apache.maven:maven-model-builder:" + this.getClass().getPackage().getImplementationVersion() + ":super-pom"; - InputSource inputSource = new InputSource(); - inputSource.setModelId( modelId ); - inputSource.setLocation( getClass().getResource( resource ).toExternalForm() ); + InputSource inputSource = new InputSource( + modelId, getClass().getResource( resource ).toExternalForm() ); options.put( ModelProcessor.INPUT_SOURCE, inputSource ); superModel = modelProcessor.read( is, options ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java index 3f44fb7e4e3c..cf8443a7ba73 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Provides the super POM that all models implicitly inherit from. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java index 93a99ccf3b9d..4a53081f37d2 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java @@ -19,33 +19,9 @@ * under the License. */ -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputLocationTracker; -import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Repository; -import org.apache.maven.model.Resource; -import org.apache.maven.model.building.ModelBuildingRequest; -import org.apache.maven.model.building.ModelProblem.Severity; -import org.apache.maven.model.building.ModelProblem.Version; -import org.apache.maven.model.building.ModelProblemCollector; -import org.apache.maven.model.building.ModelProblemCollectorRequest; -import org.apache.maven.model.interpolation.ModelVersionProcessor; -import org.codehaus.plexus.util.StringUtils; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; import java.io.File; import java.util.Arrays; @@ -58,9 +34,33 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.DistributionManagement; +import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputLocationTracker; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; +import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.Reporting; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.model.Resource; +import org.apache.maven.model.Model; +import org.apache.maven.model.building.ModelBuildingRequest; +import org.apache.maven.model.building.ModelProblem.Severity; +import org.apache.maven.model.building.ModelProblem.Version; +import org.apache.maven.model.building.ModelProblemCollector; +import org.apache.maven.model.building.ModelProblemCollectorRequest; +import org.apache.maven.model.interpolation.ModelVersionProcessor; +import org.codehaus.plexus.util.StringUtils; /** * @author Trygve Laugstøl @@ -94,8 +94,11 @@ public DefaultModelValidator( ModelVersionProcessor versionProcessor ) } @Override - public void validateFileModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems ) + public void validateFileModel( Model ma, ModelBuildingRequest request, ModelProblemCollector problems ) { + + org.apache.maven.api.model.Model m = ma.getDelegate(); + Parent parent = m.getParent(); if ( parent != null ) { @@ -239,8 +242,10 @@ public void validateFileModel( Model m, ModelBuildingRequest request, ModelProbl } @Override - public void validateRawModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems ) + public void validateRawModel( Model ma, ModelBuildingRequest request, ModelProblemCollector problems ) { + org.apache.maven.api.model.Model m = ma.getDelegate(); + Parent parent = m.getParent(); if ( parent != null ) @@ -360,8 +365,10 @@ private void validate20RawPlugins( ModelProblemCollector problems, List } @Override - public void validateEffectiveModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems ) + public void validateEffectiveModel( Model ma, ModelBuildingRequest request, ModelProblemCollector problems ) { + org.apache.maven.api.model.Model m = ma.getDelegate(); + validateStringNotEmpty( "modelVersion", problems, Severity.ERROR, Version.BASE, m.getModelVersion(), m ); validateCoordinateId( "groupId", problems, m.getGroupId(), m ); @@ -563,7 +570,8 @@ else if ( sysPath.contains( "${basedir}" ) || sysPath.contains( "${project.based } } - private void validate20RawDependenciesSelfReferencing( ModelProblemCollector problems, Model m, + private void validate20RawDependenciesSelfReferencing( ModelProblemCollector problems, + org.apache.maven.api.model.Model m, List dependencies, String prefix, ModelBuildingRequest request ) { @@ -589,7 +597,8 @@ private void validate20RawDependenciesSelfReferencing( ModelProblemCollector pro } } - private void validateEffectiveDependencies( ModelProblemCollector problems, Model m, List dependencies, + private void validateEffectiveDependencies( ModelProblemCollector problems, org.apache.maven.api.model.Model m, + List dependencies, boolean management, ModelBuildingRequest request ) { Severity errOn30 = getSeverity( request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0 ); @@ -629,7 +638,8 @@ private void validateEffectiveDependencies( ModelProblemCollector problems, Mode } } - private void validateEffectiveModelAgainstDependency( String prefix, ModelProblemCollector problems, Model m, + private void validateEffectiveModelAgainstDependency( String prefix, ModelProblemCollector problems, + org.apache.maven.api.model.Model m, Dependency d, ModelBuildingRequest request ) { String key = d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion() @@ -1357,13 +1367,11 @@ private static void addViolation( ModelProblemCollector problems, Severity sever buffer.append( ' ' ).append( message ); - // CHECKSTYLE_OFF: LineLength - problems.add( new ModelProblemCollectorRequest( severity, version ).setMessage( - buffer.toString() ).setLocation( getLocation( fieldName, tracker ) ) ); - // CHECKSTYLE_ON: LineLength + problems.add( new ModelProblemCollectorRequest( severity, version ) + .setMessage( buffer.toString() ).setLocation( getLocation( fieldName, tracker ) ) ); } - private static InputLocation getLocation( String fieldName, InputLocationTracker tracker ) + private static org.apache.maven.model.InputLocation getLocation( String fieldName, InputLocationTracker tracker ) { InputLocation location = null; @@ -1402,7 +1410,7 @@ private static InputLocation getLocation( String fieldName, InputLocationTracker } } - return location; + return location != null ? new org.apache.maven.model.InputLocation( location ) : null; } private static boolean equals( String s1, String s2 ) diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java index 98e2773ba96a..cb112834a944 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java @@ -23,8 +23,9 @@ import java.io.FileInputStream; import java.nio.file.Paths; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenXpp3Reader; import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.Test; @@ -60,7 +61,8 @@ public void testCompleteWiring() assertNotNull( result ); assertNotNull( result.getEffectiveModel() ); assertEquals( "activated", result.getEffectiveModel().getProperties().get( "profile.file" ) ); - Xpp3Dom conf = (Xpp3Dom) result.getEffectiveModel().getBuild().getPlugins().get( 0 ).getConfiguration(); + Xpp3Dom conf = ( Xpp3Dom ) result.getEffectiveModel().getBuild().getPlugins().get( 0 ).getConfiguration(); + assertNotNull( conf ); assertEquals( "1.5", conf.getChild( "source" ).getValue() ); assertEquals( " 1.5 ", conf.getChild( "target" ).getValue() ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java index 767f5fb5e504..b6734e87daef 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java @@ -1,10 +1,5 @@ package org.apache.maven.model.building; - import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.io.File; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -24,14 +19,19 @@ * under the License. */ -import org.apache.maven.model.Dependency; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; import org.apache.maven.model.resolution.InvalidRepositoryException; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; import org.junit.jupiter.api.Test; +import java.io.File; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @author Guillaume Nodet @@ -98,7 +98,7 @@ public void testCycleInImports() static class CycleInImportsResolver extends BaseModelResolver { @Override - public ModelSource resolveModel(Dependency dependency) throws UnresolvableModelException + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException { switch ( dependency.getManagementKey() ) { @@ -119,13 +119,13 @@ public ModelSource resolveModel( String groupId, String artifactId, String versi } @Override - public ModelSource resolveModel( Parent parent ) throws UnresolvableModelException + public ModelSource resolveModel( Parent parent, AtomicReference modified ) throws UnresolvableModelException { return null; } @Override - public ModelSource resolveModel( Dependency dependency ) throws UnresolvableModelException + public ModelSource resolveModel( Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { return null; } @@ -145,6 +145,32 @@ public ModelResolver newCopy() { return this; } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException + { + return null; + } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) + throws UnresolvableModelException + { + return null; + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException + { + + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository, boolean replace ) + throws InvalidRepositoryException + { + + } } @Test diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java index 286664ce14ba..dee13836af5a 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.maven.model.merge.ModelMerger; +import org.apache.maven.model.v4.MavenMerger; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -42,7 +42,7 @@ public class FileToRawModelMergerTest public void testOverriddenMergeMethods() { List methodNames = - Stream.of( ModelMerger.class.getDeclaredMethods() ) + Stream.of( MavenMerger.class.getDeclaredMethods() ) .filter( m -> m.getName().startsWith( "merge" ) ) .filter( m -> { diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java index b573ad19b1ea..a2191f0b9b8d 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java @@ -23,7 +23,7 @@ import java.io.IOException; import java.nio.file.Path; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.AbstractModelSourceTransformer; import org.apache.maven.model.building.SimpleProblemCollector; import org.apache.maven.model.building.TransformerContext; @@ -211,18 +211,18 @@ public void testInheritance( String baseName, boolean fromRepo ) { // when model is read from repo, a stream is used, then pomFile == null // (has consequences in inheritance algorithm since getProjectDirectory() returns null) - parent.setPomFile( null ); - child.setPomFile( null ); + parent = Model.newBuilder( parent, true ).pomFile( null ).build(); + child = Model.newBuilder( child, true ).pomFile( null ).build(); } SimpleProblemCollector problems = new SimpleProblemCollector(); - assembler.assembleModelInheritance( child, parent, null, problems ); + Model assembled = assembler.assembleModelInheritance( child, parent, null, problems ); // write baseName + "-actual" File actual = new File( "target/test-classes/poms/inheritance/" + baseName + ( fromRepo ? "-build" : "-repo" ) + "-actual.xml" ); - writer.write( actual, null, child ); + writer.write( actual, null, assembled ); // check with getPom( baseName + "-expected" ) File expected = getPom( baseName + "-expected" ); @@ -240,11 +240,11 @@ public void testModulePathNotArtifactId() SimpleProblemCollector problems = new SimpleProblemCollector(); - assembler.assembleModelInheritance( child, parent, null, problems ); + Model model = assembler.assembleModelInheritance( child, parent, null, problems ); File actual = new File( "target/test-classes/poms/inheritance/module-path-not-artifactId-actual.xml" ); - writer.write( actual, null, child ); + writer.write( actual, null, model ); // check with getPom( "module-path-not-artifactId-effective" ) File expected = getPom( "module-path-not-artifactId-expected" ); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java index ca9d28edd58d..ff5259fbe620 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java @@ -21,20 +21,22 @@ import java.io.File; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.TimeZone; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Repository; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Organization; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.model.Resource; +import org.apache.maven.api.model.Scm; import org.apache.maven.model.building.DefaultModelBuildingRequest; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.SimpleProblemCollector; @@ -145,12 +147,8 @@ public void testDefaultBuildTimestampFormatWithLocalTimeZoneMidnightRollover() @Test public void testShouldNotThrowExceptionOnReferenceToNonExistentValue() throws Exception { - Model model = new Model(); - - Scm scm = new Scm(); - scm.setConnection( "${test}/somepath" ); - - model.setScm( scm ); + Scm scm = Scm.newBuilder().connection( "${test}/somepath" ).build(); + Model model = Model.newBuilder().scm( scm ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -165,12 +163,8 @@ public void testShouldNotThrowExceptionOnReferenceToNonExistentValue() throws Ex @Test public void testShouldThrowExceptionOnRecursiveScmConnectionReference() throws Exception { - Model model = new Model(); - - Scm scm = new Scm(); - scm.setConnection( "${project.scm.connection}/somepath" ); - - model.setScm( scm ); + Scm scm = Scm.newBuilder().connection( "${project.scm.connection}/somepath" ).build(); + Model model = Model.newBuilder().scm( scm ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -182,14 +176,10 @@ public void testShouldThrowExceptionOnRecursiveScmConnectionReference() throws E @Test public void testShouldNotThrowExceptionOnReferenceToValueContainingNakedExpression() throws Exception { - Model model = new Model(); - - Scm scm = new Scm(); - scm.setConnection( "${test}/somepath" ); - - model.setScm( scm ); - - model.addProperty( "test", "test" ); + Scm scm = Scm.newBuilder().connection( "${test}/somepath" ).build(); + Properties props = new Properties(); + props.put( "test", "test" ); + Model model = Model.newBuilder().scm( scm ).properties( props ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -207,13 +197,9 @@ public void shouldInterpolateOrganizationNameCorrectly() throws Exception { String orgName = "MyCo"; - Model model = new Model(); - model.setName( "${project.organization.name} Tools" ); - - Organization org = new Organization(); - org.setName( orgName ); - - model.setOrganization( org ); + Model model = Model.newBuilder().name( "${project.organization.name} Tools" ) + .organization( Organization.newBuilder().name( orgName ).build() ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -226,13 +212,9 @@ public void shouldInterpolateOrganizationNameCorrectly() throws Exception @Test public void shouldInterpolateDependencyVersionToSetSameAsProjectVersion() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - - Dependency dep = new Dependency(); - dep.setVersion( "${project.version}" ); - - model.addDependency( dep ); + Model model = Model.newBuilder().version( "3.8.1" ) + .dependencies( Collections.singletonList( Dependency.newBuilder().version( "${project.version}" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -247,13 +229,9 @@ public void shouldInterpolateDependencyVersionToSetSameAsProjectVersion() throws @Test public void testShouldNotInterpolateDependencyVersionWithInvalidReference() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - - Dependency dep = new Dependency(); - dep.setVersion( "${something}" ); - - model.addDependency( dep ); + Model model = Model.newBuilder().version( "3.8.1" ) + .dependencies( Collections.singletonList( Dependency.newBuilder().version( "${something}" ).build() ) ) + .build(); /* // This is the desired behaviour, however there are too many crappy poms in the repo and an issue with the @@ -283,14 +261,10 @@ public void testShouldNotInterpolateDependencyVersionWithInvalidReference() thro @Test public void testTwoReferences() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - model.setArtifactId( "foo" ); - - Dependency dep = new Dependency(); - dep.setVersion( "${project.artifactId}-${project.version}" ); - - model.addDependency( dep ); + Model model = Model.newBuilder().version( "3.8.1" ).artifactId( "foo" ) + .dependencies( Collections.singletonList( + Dependency.newBuilder().version( "${project.artifactId}-${project.version}" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -305,15 +279,10 @@ public void testTwoReferences() throws Exception @Test public void testBasedir() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - model.setArtifactId( "foo" ); - - Repository repository = new Repository(); - - repository.setUrl( "file://localhost/${basedir}/temp-repo" ); - - model.addRepository( repository ); + Model model = Model.newBuilder().version( "3.8.1" ).artifactId( "foo" ) + .repositories( Collections.singletonList( + Repository.newBuilder().url( "file://localhost/${basedir}/temp-repo" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -327,15 +296,10 @@ public void testBasedir() throws Exception @Test public void testBaseUri() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - model.setArtifactId( "foo" ); - - Repository repository = new Repository(); - - repository.setUrl( "${project.baseUri}/temp-repo" ); - - model.addRepository( repository ); + Model model = Model.newBuilder().version( "3.8.1" ).artifactId( "foo" ) + .repositories( Collections.singletonList( + Repository.newBuilder().url( "${project.baseUri}/temp-repo" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -350,16 +314,12 @@ public void testBaseUri() throws Exception public void testEnvars() throws Exception { Properties context = new Properties(); - context.put( "env.HOME", "/path/to/home" ); - Model model = new Model(); - Properties modelProperties = new Properties(); - modelProperties.setProperty( "outputDirectory", "${env.HOME}" ); - model.setProperties( modelProperties ); + Model model = Model.newBuilder().properties( modelProperties ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -374,13 +334,11 @@ public void testEnvars() throws Exception @Test public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception { - Model model = new Model(); Properties modelProperties = new Properties(); - modelProperties.setProperty( "outputDirectory", "${env.DOES_NOT_EXIST}" ); - model.setProperties( modelProperties ); + Model model = Model.newBuilder().properties( modelProperties ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -395,13 +353,10 @@ public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws E @Test public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception { - Model model = new Model(); - Properties modelProperties = new Properties(); - modelProperties.setProperty( "outputDirectory", "${DOES_NOT_EXIST}" ); - model.setProperties( modelProperties ); + Model model = Model.newBuilder().properties( modelProperties ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -416,17 +371,14 @@ public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Except @Test public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorrectly() throws Exception { - Model model = new Model(); - - Build build = new Build(); - build.setSourceDirectory( "correct" ); - - Resource res = new Resource(); - res.setDirectory( "${project.build.sourceDirectory}" ); - - build.addResource( res ); - - model.setBuild( build ); + Model model = Model.newBuilder() + .build( Build.newBuilder() + .sourceDirectory( "correct" ) + .resources( Arrays.asList( + Resource.newBuilder().directory( "${project.build.sourceDirectory}" ).build() + ) ) + .build() ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -438,18 +390,17 @@ public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorre List outResources = out.getBuild().getResources(); Iterator resIt = outResources.iterator(); - assertEquals( build.getSourceDirectory(), resIt.next().getDirectory() ); + assertEquals( model.getBuild().getSourceDirectory(), resIt.next().getDirectory() ); } @Test public void shouldInterpolateUnprefixedBasedirExpression() throws Exception { File basedir = new File( "/test/path" ); - Model model = new Model(); - Dependency dep = new Dependency(); - dep.setSystemPath( "${basedir}/artifact.jar" ); - - model.addDependency( dep ); + Model model = Model.newBuilder() + .dependencies( Collections.singletonList( + Dependency.newBuilder().systemPath( "${basedir}/artifact.jar" ).build() + ) ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -474,8 +425,7 @@ public void testRecursiveExpressionCycleNPE() throws Exception props.setProperty( "bb", "${aa}" ); DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - Model model = new Model(); - model.setProperties( props ); + Model model = Model.newBuilder().properties( props ).build(); SimpleProblemCollector collector = new SimpleProblemCollector(); ModelInterpolator interpolator = createInterpolator(); @@ -492,8 +442,7 @@ public void testRecursiveExpressionCycleBaseDir() throws Exception props.setProperty( "basedir", "${basedir}" ); DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - Model model = new Model(); - model.setProperties( props ); + Model model = Model.newBuilder().properties( props ).build(); SimpleProblemCollector collector = new SimpleProblemCollector(); ModelInterpolator interpolator = createInterpolator(); @@ -511,13 +460,10 @@ public void shouldIgnorePropertiesWithPomPrefix() throws Exception final String orgName = "MyCo"; final String expectedName = "${pom.organization.name} Tools"; - Model model = new Model(); - model.setName( expectedName ); - - Organization org = new Organization(); - org.setName( orgName ); - - model.setOrganization( org ); + Model model = Model.newBuilder() + .name( expectedName ) + .organization( Organization.newBuilder().name( orgName ).build() ) + .build(); ModelInterpolator interpolator = createInterpolator(); SimpleProblemCollector collector = new SimpleProblemCollector(); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java deleted file mode 100644 index cc2f2970c8e4..000000000000 --- a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java +++ /dev/null @@ -1,618 +0,0 @@ -package org.apache.maven.model.interpolation; - -/* - * 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. - */ - -import java.io.File; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; - -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; -import org.apache.maven.model.building.DefaultModelBuildingRequest; -import org.apache.maven.model.building.ModelBuildingRequest; -import org.apache.maven.model.building.SimpleProblemCollector; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.CoreMatchers.anyOf; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** - * StringSearchModelInterpolatorTest - not in use - * - * @author jdcasey - * @author Benjamin Bentmann - * @deprecated replaced by StringVisitorModelInterpolator (MNG-6697) - */ -public class StringSearchModelInterpolatorTest - extends AbstractModelInterpolatorTest -{ - protected ModelInterpolator createInterpolator() - { - return new StringSearchModelInterpolator( null, null, new DefaultModelVersionProcessor() ); - } - - @Test - public void testInterpolateStringArray() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - String[] values = { "${key}", "${key2}" }; - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest(p); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( values, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", values[0] ); - assertEquals( "value2", values[1] ); - } - - private ModelBuildingRequest createModelBuildingRequest( Properties p ) - { - ModelBuildingRequest config = new DefaultModelBuildingRequest(); - config.setSystemProperties( p ); - return config; - } - - @Test - public void testInterpolateObjectWithStringArrayField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - String[] values = { "${key}", "${key2}" }; - - ObjectWithStringArrayField obj = new ObjectWithStringArrayField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", obj.values[0] ); - assertEquals( "value2", obj.values[1] ); - } - - @Test - public void testInterpolateObjectWithStringListField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - List values = new ArrayList<>(); - values.add( "${key}" ); - values.add( "${key2}" ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", obj.values.get( 0 ) ); - assertEquals( "value2", obj.values.get( 1 ) ); - } - - @Test - public void testInterpolateObjectWithStringListFieldAndOneLiteralValue() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - List values = new ArrayList<>(); - values.add( "key" ); - values.add( "${key2}" ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "key", obj.values.get( 0 ) ); - assertEquals( "value2", obj.values.get( 1 ) ); - } - - @Test - public void testInterpolateObjectWithUnmodifiableStringListField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - List values = Collections.unmodifiableList( Collections.singletonList( "${key}" ) ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "${key}", obj.values.get( 0 ) ); - } - - @Test - public void testInterpolateObjectWithStringArrayListField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - p.setProperty( "key3", "value3" ); - p.setProperty( "key4", "value4" ); - - List values = new ArrayList<>(); - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", ( (String[]) obj.values.get( 0 ) )[0] ); - assertEquals( "value2", ( (String[]) obj.values.get( 0 ) )[1] ); - assertEquals( "value3", ( (String[]) obj.values.get( 1 ) )[0] ); - assertEquals( "value4", ( (String[]) obj.values.get( 1 ) )[1] ); - } - - @Test - public void testInterpolateObjectWithStringToStringMapField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - Map values = new HashMap<>(); - values.put( "key", "${key}" ); - values.put( "key2", "${key2}" ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", obj.values.get( "key" ) ); - assertEquals( "value2", obj.values.get( "key2" ) ); - } - - @Test - public void testInterpolateObjectWithStringToStringMapFieldAndOneLiteralValue() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - Map values = new HashMap<>(); - values.put( "key", "val" ); - values.put( "key2", "${key2}" ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "val", obj.values.get( "key" ) ); - assertEquals( "value2", obj.values.get( "key2" ) ); - } - - @Test - public void testInterpolateObjectWithUnmodifiableStringToStringMapField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - Map values = Collections.unmodifiableMap( Collections.singletonMap( "key", "${key}" ) ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "${key}", obj.values.get( "key" ) ); - } - - @Test - public void testInterpolateObjectWithStringToStringArrayMapField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - p.setProperty( "key3", "value3" ); - p.setProperty( "key4", "value4" ); - - Map values = new HashMap<>(); - values.put( "key", new String[] { "${key}", "${key2}" } ); - values.put( "key2", new String[] { "${key3}", "${key4}" } ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", ( (String[]) obj.values.get( "key" ) )[0] ); - assertEquals( "value2", ( (String[]) obj.values.get( "key" ) )[1] ); - assertEquals( "value3", ( (String[]) obj.values.get( "key2" ) )[0] ); - assertEquals( "value4", ( (String[]) obj.values.get( "key2" ) )[1] ); - } - - @Test - public void testInterpolateObjectWithPomFile() - throws Exception - { - Model model = new Model(); - model.setPomFile( new File( System.getProperty( "user.dir" ), "pom.xml" ) ); - File baseDir = model.getProjectDirectory(); - - Properties p = new Properties(); - - Map values = new HashMap<>(); - values.put( "key", "${project.basedir}" + File.separator + "target" ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertThat( baseDir.getAbsolutePath(), is( System.getProperty( "user.dir" ) ) ); - assertThat( obj.values.size(), is( 1 ) ); - assertThat( (String) obj.values.get( "key" ), is( anyOf( - is( System.getProperty( "user.dir" ) + File.separator + "target" ), - // TODO why MVN adds dot /./ in paths??? - is( System.getProperty( "user.dir" ) + File.separator + '.' + File.separator + "target" ) - ) ) ); - } - - @Test - public void testNotInterpolateObjectWithFile() - throws Exception - { - Model model = new Model(); - - File baseDir = new File( System.getProperty( "user.dir" ) ); - - Properties p = new Properties(); - - ObjectWithNotInterpolatedFile obj = new ObjectWithNotInterpolatedFile( baseDir ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - Map, ?> cache = getCachedEntries(); - - Object objCacheItem = cache.get( Object.class ); - Object fileCacheItem = cache.get( File.class ); - - assertNotNull( objCacheItem ); - assertNotNull( fileCacheItem ); - - assertThat( readFieldsArray( objCacheItem ).length, is( 0 ) ); - assertThat( readFieldsArray( fileCacheItem ).length, is( 0 ) ); - } - - private static Object[] readFieldsArray( Object o ) throws NoSuchFieldException, IllegalAccessException - { - assertNotNull( o ); - Field field = o.getClass().getDeclaredField( "fields" ); - field.setAccessible( true ); - return (Object[]) field.get( o ); - } - - private static Map, ?> getCachedEntries() throws NoSuchFieldException, IllegalAccessException - { - Field field = StringSearchModelInterpolator.class.getDeclaredField( "CACHED_ENTRIES" ); - field.setAccessible( true ); - //noinspection unchecked - return (Map, ?>) field.get( null ); - } - - @Test - public void testNotInterpolateFile() - throws Exception - { - Model model = new Model(); - - File baseDir = new File( System.getProperty( "user.dir" ) ); - - Properties p = new Properties(); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( baseDir, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - Map, ?> cache = getCachedEntries(); - - Object fileCacheItem = cache.get( File.class ); - - assertNotNull( fileCacheItem ); - - assertThat( readFieldsArray( fileCacheItem ).length, is( 0 ) ); - } - - - @Test - public void testConcurrentInterpolation() - throws Exception - { - final Model model = new Model(); - - final Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - p.setProperty( "key3", "value3" ); - p.setProperty( "key4", "value4" ); - p.setProperty( "key5", "value5" ); - - final StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - int numItems = 100; - final CountDownLatch countDownLatch = new CountDownLatch(1); - - List> futures = new ArrayList<>(); - for ( int i = 0; i < numItems; i++ ) - { - Callable future = () -> - { - final ObjectWithMixedProtection obj = getValueList(); - final ModelBuildingRequest config = createModelBuildingRequest( p ); - - countDownLatch.await(); - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - return collector; - }; - FutureTask task = new FutureTask<>( future ); - futures.add( task ); - new Thread( task ).start(); - } - countDownLatch.countDown(); // Start all the threads - for ( Future result : futures ) - { - SimpleProblemCollector problemCollector = result.get(); // ArrayIndexOutOfBoundsException are typical indication of threading issues - assertProblemFree( problemCollector ); - } - } - - private ObjectWithMixedProtection getValueList() - { - List values = new ArrayList<>(); - - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - List values2 = new ArrayList<>(); - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - List values3 = new ArrayList<>(); - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - - return new ObjectWithMixedProtection( values, values2, values3, "${key5}" ); - } - - private static final class ObjectWithStringArrayField - { - private final String[] values; - - public ObjectWithStringArrayField( String[] values ) - { - this.values = values; - } - } - - private static final class ObjectWithListField - { - private final List values; - - public ObjectWithListField( List values ) - { - this.values = values; - } - } - - private static final class ObjectWithMapField - { - private final Map values; - - public ObjectWithMapField( Map values ) - { - this.values = values; - } - } - - private static final class ObjectWithNotInterpolatedFile - { - private final File f; - - ObjectWithNotInterpolatedFile( File f ) - { - this.f = f; - } - } - - @SuppressWarnings( "unused" ) - private static final class ObjectWithMixedProtection - { - private List values1; - protected List values2; - List values3; - private String fooBar; - - private ObjectWithMixedProtection( List values1, List values2, List values3 ) - { - this.values1 = values1; - this.values2 = values2; - this.values3 = values3; - } - - private ObjectWithMixedProtection( List values1, List values2, List values3, String fooBar ) - { - this.values1 = values1; - this.values2 = values2; - this.values3 = values3; - this.fooBar = fooBar; - } - - public String getFooBar() - { - return fooBar; - } - } - - @Test - public void testFinalFieldsExcludedFromInterpolation() - { - Properties props = new Properties(); - props.setProperty( "expression", "value" ); - DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - request.setUserProperties( props ); - - SimpleProblemCollector problems = new SimpleProblemCollector(); - StringSearchModelInterpolator interpolator = - new StringSearchModelInterpolator( null, null, new DefaultModelVersionProcessor() ); - interpolator.interpolateObject( new ClassWithFinalField(), new Model(), null, request, problems ); - - assertProblemFree( problems ); - } - - static class ClassWithFinalField - { - public static final String CONSTANT = "${expression}"; - } - - @Test - public void locationTrackerShouldBeExcludedFromInterpolation() - { - Properties props = new Properties(); - props.setProperty( "expression", "value" ); - DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - request.setUserProperties( props ); - - InputSource source = new InputSource(); - source.setLocation( "${expression}" ); - source.setModelId( "${expression}" ); - Model model = new Model(); - model.setLocation( "", new InputLocation( 1, 1, source ) ); - - SimpleProblemCollector problems = new SimpleProblemCollector(); - StringSearchModelInterpolator interpolator = - new StringSearchModelInterpolator( null, null, new DefaultModelVersionProcessor() ); - interpolator.interpolateObject( model, model, null, request, problems ); - - assertProblemFree( problems ); - assertEquals( "${expression}", source.getLocation() ); - assertEquals( "${expression}", source.getModelId() ); - } - -} diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java index 8fa92cecf9b7..e4b11cca8c35 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java @@ -23,6 +23,6 @@ public class StringVisitorModelInterpolatorTest extends AbstractModelInterpolato { protected ModelInterpolator createInterpolator() { - return new StringVisitorModelInterpolator( null, null, new DefaultModelVersionProcessor() ); + return new StringVisitorModelInterpolator( null, null ); } } \ No newline at end of file diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java index 636f3fb571b8..a8d2584050ff 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java @@ -22,9 +22,9 @@ import java.util.Collections; -import org.apache.maven.model.Model; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Prerequisites; +import org.apache.maven.api.model.Profile; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -38,64 +38,66 @@ public class MavenModelMergerTest @Test public void testMergeModel_ModelVersion() { - Model parent = new Model(); - parent.setModelVersion( "4.0.0" ); - Model model = new Model(); - modelMerger.mergeModel_ModelVersion( model, parent, false, null ); - assertNull( model.getModelVersion() ); + Model parent = Model.newBuilder().modelVersion( "4.0.0" ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_ModelVersion( builder, model, parent, false, null ); + assertNull( builder.build().getModelVersion() ); - model.setModelVersion( "5.0.0" ); - modelMerger.mergeModel_ModelVersion( model, parent, false, null ); - assertEquals( "5.0.0", model.getModelVersion() ); + model = Model.newBuilder().modelVersion( "5.0.0" ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_ModelVersion( builder, model, parent, false, null ); + assertEquals( "5.0.0", builder.build().getModelVersion() ); } // ArtifactId is neither inherited nor injected @Test public void testMergeModel_ArtifactId() { - Model parent = new Model(); - parent.setArtifactId( "PARENT" ); - Model model = new Model(); - modelMerger.mergeModel_ArtifactId( model, parent, false, null ); + Model parent = Model.newBuilder().artifactId( "PARENT" ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_ArtifactId( builder, model, parent, false, null ); assertNull( model.getArtifactId() ); - model.setArtifactId( "MODEL" ); - modelMerger.mergeModel_ArtifactId( model, parent, false, null ); - assertEquals( "MODEL", model.getArtifactId() ); + model = Model.newBuilder().artifactId( "MODEL" ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_ArtifactId( builder, model, parent, false, null ); + assertEquals( "MODEL", builder.build().getArtifactId() ); } // Prerequisites are neither inherited nor injected @Test public void testMergeModel_Prerequisites() { - Model parent = new Model(); - parent.setPrerequisites( new Prerequisites() ); - Model model = new Model(); - modelMerger.mergeModel_Prerequisites( model, parent, false, null ); - assertNull( model.getPrerequisites() ); + Model parent = Model.newBuilder().prerequisites( Prerequisites.newInstance() ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_Prerequisites( builder, model, parent, false, null ); + assertNull( builder.build().getPrerequisites() ); - Prerequisites modelPrerequisites = new Prerequisites(); - modelPrerequisites.setMaven( "3.0" ); - model.setPrerequisites( modelPrerequisites ); - modelMerger.mergeModel_Prerequisites( model, parent, false, null ); - assertEquals( modelPrerequisites, model.getPrerequisites() ); + Prerequisites modelPrerequisites = Prerequisites.newBuilder().maven( "3.0" ).build(); + model = Model.newBuilder().prerequisites( modelPrerequisites ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_Prerequisites( builder, model, parent, false, null ); + assertEquals( modelPrerequisites, builder.build().getPrerequisites() ); } // Profiles are neither inherited nor injected @Test public void testMergeModel_Profiles() { - Model parent = new Model(); - parent.setProfiles( Collections.singletonList( new Profile() ) );; - Model model = new Model(); - modelMerger.mergeModel_Profiles( model, parent, false, null ); - assertEquals( 0, model.getProfiles().size() ); + Model parent = Model.newBuilder().profiles( Collections.singletonList( Profile.newInstance() ) ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_Profiles( builder, model, parent, false, null ); + assertEquals( 0, builder.build().getProfiles().size() ); - Profile modelProfile = new Profile(); - modelProfile.setId( "MODEL" ); - model.setProfiles( Collections.singletonList( modelProfile ) ); - modelMerger.mergeModel_Prerequisites( model, parent, false, null ); - assertEquals( Collections.singletonList( modelProfile ), model.getProfiles() ); + Profile modelProfile = Profile.newBuilder().id( "MODEL" ).build(); + model = Model.newBuilder().profiles( Collections.singletonList( modelProfile ) ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_Prerequisites( builder, model, parent, false, null ); + assertEquals( Collections.singletonList( modelProfile ), builder.build().getProfiles() ); } } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java index 6140fc511f40..6cd95e946a39 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java @@ -21,7 +21,7 @@ import java.util.Properties; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.SimpleProblemCollector; import org.apache.maven.model.profile.DefaultProfileActivationContext; import org.apache.maven.model.profile.ProfileActivationContext; @@ -59,7 +59,7 @@ protected void assertActivation( boolean active, Profile profile, ProfileActivat { SimpleProblemCollector problems = new SimpleProblemCollector(); - assertEquals( active, activator.isActive( profile, context, problems ) ); + assertEquals( active, activator.isActive( new org.apache.maven.model.Profile( profile ), context, problems ) ); assertEquals( 0, problems.getErrors().size(), problems.getErrors().toString() ); assertEquals( 0, problems.getWarnings().size(), problems.getWarnings().toString() ); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java index 300fc1353934..f7edf1fc35e7 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java @@ -19,9 +19,9 @@ * under the License. */ -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.path.DefaultPathTranslator; import org.apache.maven.model.path.ProfileActivationFilePathInterpolator; import org.apache.maven.model.profile.DefaultProfileActivationContext; @@ -100,26 +100,22 @@ public void testIsActiveExistsLeavesFileUnchanged() private Profile newExistsProfile( String filePath ) { - ActivationFile activationFile = new ActivationFile(); - activationFile.setExists( filePath ); + ActivationFile activationFile = ActivationFile.newBuilder() + .exists( filePath ).build(); return newProfile( activationFile ); } private Profile newMissingProfile( String filePath ) { - ActivationFile activationFile = new ActivationFile(); - activationFile.setMissing( filePath ); + ActivationFile activationFile = ActivationFile.newBuilder() + .missing( filePath ).build(); return newProfile( activationFile ); } private Profile newProfile( ActivationFile activationFile ) { - Activation activation = new Activation(); - activation.setFile( activationFile ); - - Profile profile = new Profile(); - profile.setActivation( activation ); - - return profile; + Activation activation = Activation.newBuilder() + .file( activationFile ).build(); + return Profile.newBuilder().activation( activation ).build(); } } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java index ce57bf0dad99..dbfb4749416c 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java @@ -21,8 +21,8 @@ import java.util.Properties; -import org.apache.maven.model.Activation; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.Profile; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -44,11 +44,9 @@ void setUp() throws Exception private Profile newProfile(String jdkVersion ) { - Activation a = new Activation(); - a.setJdk( jdkVersion ); + Activation a = Activation.newBuilder().jdk( jdkVersion ).build(); - Profile p = new Profile(); - p.setActivation( a ); + Profile p = Profile.newBuilder().activation( a ).build(); return p; } @@ -64,11 +62,11 @@ private Properties newProperties( String javaVersion ) public void testNullSafe() throws Exception { - Profile p = new Profile(); + Profile p = Profile.newInstance(); assertActivation( false, p, newContext( null, null ) ); - p.setActivation( new Activation() ); + p = p.withActivation( Activation.newInstance() ); assertActivation( false, p, newContext( null, null ) ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java index 72a6775623b5..2114dc5ac7c4 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java @@ -21,9 +21,9 @@ import java.util.Properties; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationProperty; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationProperty; +import org.apache.maven.api.model.Profile; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,15 +45,14 @@ void setUp() throws Exception private Profile newProfile(String key, String value ) { - ActivationProperty ap = new ActivationProperty(); - ap.setName( key ); - ap.setValue( value ); + ActivationProperty ap = ActivationProperty.newBuilder() + .name( key ) + .value( value ) + .build(); - Activation a = new Activation(); - a.setProperty( ap ); + Activation a = Activation.newBuilder().property( ap ).build(); - Profile p = new Profile(); - p.setActivation( a ); + Profile p = Profile.newBuilder().activation( a ).build(); return p; } @@ -69,11 +68,11 @@ private Properties newProperties( String key, String value ) public void testNullSafe() throws Exception { - Profile p = new Profile(); + Profile p = Profile.newInstance(); assertActivation( false, p, newContext( null, null ) ); - p.setActivation( new Activation() ); + p = p.withActivation( Activation.newInstance() ); assertActivation( false, p, newContext( null, null ) ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java index 57dae7ccbe0d..2c637004492f 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java @@ -27,7 +27,7 @@ import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.SimpleProblemCollector; import org.apache.maven.model.interpolation.DefaultModelVersionProcessor; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.model.v4.MavenXpp3Reader; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -50,7 +50,7 @@ private Model read( String pom ) String resource = "/poms/validation/" + pom; InputStream is = getClass().getResourceAsStream( resource ); assertNotNull( is, "missing resource: " + resource ); - return new MavenXpp3Reader().read( is ); + return new Model( new MavenXpp3Reader().read( is ) ); } private SimpleProblemCollector validate( String pom ) diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java index e3662686aba4..cbdb65d21ba2 100644 --- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java +++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java @@ -25,6 +25,7 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.Objects; +import java.util.regex.Pattern; import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -38,6 +39,8 @@ public class BufferingParser implements XmlPullParser { + private static final Pattern WHITESPACE_REGEX = Pattern.compile( "[ \r\t\n]+" ); + protected XmlPullParser xmlPullParser; protected Deque events; protected Event current; @@ -200,7 +203,7 @@ public boolean isWhitespace() throws XmlPullParserException { if ( current.event == TEXT || current.event == CDSECT ) { - return current.text.matches( "[ \r\t\n]+" ); + return WHITESPACE_REGEX.matcher( current.text ).matches(); } else if ( current.event == IGNORABLE_WHITESPACE ) { diff --git a/maven-model/pom.xml b/maven-model/pom.xml index 10f1d2b81802..01b679687562 100644 --- a/maven-model/pom.xml +++ b/maven-model/pom.xml @@ -35,35 +35,88 @@ under the License. - org.codehaus.plexus - plexus-utils + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT - org.codehaus.modello - modello-maven-plugin - - 4.0.0 - - src/main/mdo/maven.mdo - - + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-model + generate-sources + + copy + + + + + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + mdo + target/mdo/ + maven.mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT - modello + velocity + generate-sources - java - xpp3-reader - xpp3-extended-reader - xpp3-writer - xpp3-extended-writer + velocity + + 4.0.0 + + target/mdo/maven.mdo + + + + + + + + + + + + packageModelV3=org.apache.maven.model + packageModelV4=org.apache.maven.api.model + packageToolV4=org.apache.maven.model.v4 + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + diff --git a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java new file mode 100644 index 000000000000..69536fd4a41e --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java @@ -0,0 +1,73 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.io.Serializable; + +public abstract class BaseObject + implements Serializable, Cloneable, InputLocationTracker +{ + protected ChildrenTracking childrenTracking; + protected Object delegate; + + public BaseObject() + { + } + + public BaseObject( Object delegate, BaseObject parent ) + { + this.delegate = delegate; + this.childrenTracking = parent != null ? parent::replace : null; + } + + public BaseObject( Object delegate, ChildrenTracking parent ) + { + this.delegate = delegate; + this.childrenTracking = parent; + } + + public Object getDelegate() + { + return delegate; + } + + public void update( Object newDelegate ) + { + if ( delegate != newDelegate ) + { + if ( childrenTracking != null ) + { + childrenTracking.replace( delegate, newDelegate ); + } + delegate = newDelegate; + } + } + + protected boolean replace( Object oldDelegate, Object newDelegate ) + { + return false; + } + + @FunctionalInterface + protected interface ChildrenTracking + { + boolean replace( Object oldDelegate, Object newDelegate ); + } +} diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java new file mode 100644 index 000000000000..6b6ba9d9266e --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java @@ -0,0 +1,429 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.util.stream.Collectors; + +/** + * Class InputLocation. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings( "all" ) +public final class InputLocation + implements java.io.Serializable, Cloneable, InputLocationTracker +{ + + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * The one-based line number. The value will be non-positive if + * unknown. + */ + private int lineNumber = -1; + + /** + * The one-based column number. The value will be non-positive + * if unknown. + */ + private int columnNumber = -1; + + /** + * Field source. + */ + private InputSource source; + + /** + * Field locations. + */ + private java.util.Map locations; + + /** + * Field location. + */ + private InputLocation location; + + + //----------------/ + //- Constructors -/ + //----------------/ + + public InputLocation( org.apache.maven.api.model.InputLocation location ) + { + this.lineNumber = location.getLineNumber(); + this.columnNumber = location.getColumnNumber(); + this.source = location.getSource() != null ? new InputSource( location.getSource() ) : null; + this.locations = location.getLocations().isEmpty() ? null + : location.getLocations().entrySet().stream().collect( + Collectors.toMap( e -> e.getKey(), + e -> e.getValue() == location ? this : new InputLocation( e.getValue() ) ) ); + } + + public InputLocation( int lineNumber, int columnNumber) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + } //-- org.apache.maven.model.InputLocation(int, int) + + public InputLocation(int lineNumber, int columnNumber, InputSource source) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.source = source; + } //-- org.apache.maven.model.InputLocation(int, int, InputSource) + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method clone. + * + * @return InputLocation + */ + public InputLocation clone() + { + try + { + InputLocation copy = (InputLocation) super.clone(); + + if ( copy.locations != null ) + { + copy.locations = new java.util.LinkedHashMap( copy.locations ); + } + + return copy; + } + catch ( Exception ex ) + { + throw (RuntimeException) new UnsupportedOperationException( getClass().getName() + + " does not support clone()" ).initCause( ex ); + } + } //-- InputLocation clone() + + /** + * Get the one-based column number. The value will be + * non-positive if unknown. + * + * @return int + */ + public int getColumnNumber() + { + return this.columnNumber; + } //-- int getColumnNumber() + + /** + * Get the one-based line number. The value will be + * non-positive if unknown. + * + * @return int + */ + public int getLineNumber() + { + return this.lineNumber; + } //-- int getLineNumber() + + /** + * + * + * @param key + * @return InputLocation + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + case "" : + { + return this.location; + } + default : + { + return getOtherLocation( key ); + } + } + } + else + { + return getOtherLocation( key ); + } + } //-- InputLocation getLocation( Object ) + + /** + * + * + * @return Map + */ + public java.util.Map getLocations() + { + return locations; + } //-- java.util.Map getLocations() + + /** + * + * + * @param key + * @param location + */ + public void setLocation( Object key, InputLocation location ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + case "" : + { + this.location = location; + return; + } + default : + { + setOtherLocation( key, location ); + return; + } + } + } + else + { + setOtherLocation( key, location ); + } + } //-- void setLocation( Object, InputLocation ) + + /** + * + * + * @param key + * @param location + */ + public void setOtherLocation( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new java.util.LinkedHashMap(); + } + this.locations.put( key, location ); + } + } //-- void setOtherLocation( Object, InputLocation ) + + /** + * + * + * @param key + * @return InputLocation + */ + private InputLocation getOtherLocation( Object key ) + { + return ( locations != null ) ? locations.get( key ) : null; + } //-- InputLocation getOtherLocation( Object ) + + /** + * Get the source field. + * + * @return InputSource + */ + public InputSource getSource() + { + return this.source; + } //-- InputSource getSource() + + /** + * Method merge. + * + * @param target + * @param sourceDominant + * @param source + * @return InputLocation + */ + public static InputLocation merge( InputLocation target, InputLocation source, boolean sourceDominant ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + InputLocation result = + new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource() ); + + java.util.Map locations; + java.util.Map sourceLocations = source.getLocations(); + java.util.Map targetLocations = target.getLocations(); + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new java.util.LinkedHashMap(); + locations.putAll( sourceDominant ? targetLocations : sourceLocations ); + locations.putAll( sourceDominant ? sourceLocations : targetLocations ); + } + result.setLocations( locations ); + + return result; + } //-- InputLocation merge( InputLocation, InputLocation, boolean ) + + /** + * Method merge. + * + * @param target + * @param indices + * @param source + * @return InputLocation + */ + public static InputLocation merge( InputLocation target, InputLocation source, java.util.Collection indices ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + InputLocation result = + new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource() ); + + java.util.Map locations; + java.util.Map sourceLocations = source.getLocations(); + java.util.Map targetLocations = target.getLocations(); + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new java.util.LinkedHashMap(); + for ( java.util.Iterator it = indices.iterator(); it.hasNext(); ) + { + InputLocation location; + Integer index = it.next(); + if ( index.intValue() < 0 ) + { + location = sourceLocations.get( Integer.valueOf( ~index.intValue() ) ); + } + else + { + location = targetLocations.get( index ); + } + locations.put( Integer.valueOf( locations.size() ), location ); + } + } + result.setLocations( locations ); + + return result; + } //-- InputLocation merge( InputLocation, InputLocation, java.util.Collection ) + + /** + * + * + * @param locations + */ + public void setLocations( java.util.Map locations ) + { + this.locations = locations; + } //-- void setLocations( java.util.Map ) + + + public org.apache.maven.api.model.InputLocation toApiLocation() + { + if ( locations != null && locations.values().contains( this ) ) + { + if ( locations.size() == 1 && locations.values().iterator().next() == this ) + { + return new org.apache.maven.api.model.InputLocation( + lineNumber, columnNumber, + source != null ? source.toApiSource() : null, + locations.keySet().iterator().next() ); + } + else + { + return new org.apache.maven.api.model.InputLocation( + lineNumber, columnNumber, + source != null ? source.toApiSource() : null ); + } + } + else + { + return new org.apache.maven.api.model.InputLocation( + lineNumber, columnNumber, + source != null ? source.toApiSource() : null, + locations != null ? locations.entrySet().stream().collect( + Collectors.toMap( e -> e.getKey(), e -> e.getValue().toApiLocation() ) ) : null + ); + } + } + + //-----------------/ + //- Inner Classes -/ + //-----------------/ + + /** + * Class StringFormatter. + * + * @version $Revision$ $Date$ + */ + public abstract static class StringFormatter + { + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method toString. + * + * @param location + * @return String + */ + public abstract String toString( InputLocation location ); + + } + + + + + @Override + public String toString() + { + return getLineNumber() + " : " + getColumnNumber() + ", " + getSource(); + } + + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java b/maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java new file mode 100644 index 000000000000..62a69817d1f5 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java @@ -0,0 +1,54 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +/** + * Interface InputLocationTracker. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings( "all" ) +public interface InputLocationTracker +{ + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Gets the location of the specified field in the input + * source. + * + * @param field The key of the field, must not be + * null. + * @return The location of the field in the input source or + * null if unknown. + */ + public InputLocation getLocation( Object field ); + /** + * Sets the location of the specified field. + * + * @param field The key of the field, must not be + * null. + * @param location The location of the field, may be + * null. + */ + public void setLocation( Object field, InputLocation location ); +} diff --git a/maven-model/src/main/java/org/apache/maven/model/InputSource.java b/maven-model/src/main/java/org/apache/maven/model/InputSource.java new file mode 100644 index 000000000000..2f21c4981f9b --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/InputSource.java @@ -0,0 +1,150 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +/** + * Class InputSource. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings( "all" ) +public class InputSource + implements java.io.Serializable, Cloneable +{ + + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * + * + * The identifier of the POM in the format {@code + * ::}. + * + * + */ + private String modelId; + + /** + * + * + * The path/URL of the POM or {@code null} if + * unknown. + * + * + */ + private String location; + + + //----------------/ + //- Constructors -/ + //----------------/ + + public InputSource() + { + } + + public InputSource( org.apache.maven.api.model.InputSource source ) + { + this.modelId = source.getModelId(); + this.location = source.getLocation(); + } + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method clone. + * + * @return InputSource + */ + public InputSource clone() + { + try + { + InputSource copy = (InputSource) super.clone(); + + return copy; + } + catch ( Exception ex ) + { + throw (RuntimeException) new UnsupportedOperationException( getClass().getName() + + " does not support clone()" ).initCause( ex ); + } + } //-- InputSource clone() + + /** + * Get the path/URL of the POM or {@code null} if unknown. + * + * @return String + */ + public String getLocation() + { + return this.location; + } //-- String getLocation() + + /** + * Get the identifier of the POM in the format {@code + * ::}. + * + * @return String + */ + public String getModelId() + { + return this.modelId; + } //-- String getModelId() + + /** + * Set the path/URL of the POM or {@code null} if unknown. + * + * @param location + */ + public void setLocation( String location ) + { + this.location = location; + } //-- void setLocation( String ) + + /** + * Set the identifier of the POM in the format {@code + * ::}. + * + * @param modelId + */ + public void setModelId( String modelId ) + { + this.modelId = modelId; + } //-- void setModelId( String ) + + + + @Override + public String toString() + { + return getModelId() + " " + getLocation(); + } + + public org.apache.maven.api.model.InputSource toApiSource() + { + return new org.apache.maven.api.model.InputSource( modelId, location ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/WrapperList.java b/maven-model/src/main/java/org/apache/maven/model/WrapperList.java new file mode 100644 index 000000000000..4d427d334576 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/WrapperList.java @@ -0,0 +1,129 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperList extends AbstractList +{ + private final Supplier> getter; + private final Consumer> setter; + private final Function mapper; + private final Function revMapper; + + WrapperList( List list, Function mapper, Function revMapper ) + { + this( () -> list, null, mapper, revMapper ); + } + + WrapperList( Supplier> getter, Consumer> setter, + Function mapper, Function revMapper ) + { + this.getter = getter; + this.setter = setter; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( getter.get().get( index ) ); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean add( T t ) + { + Objects.requireNonNull( t ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + boolean ret = list.add( revMapper.apply( t ) ); + setter.accept( list ); + return ret; + } + else + { + return getter.get().add( revMapper.apply( t ) ); + } + } + + @Override + public T set( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.set( index, revMapper.apply( element ) ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().set( index, revMapper.apply( element ) ) ); + } + } + + @Override + public void add( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + list.add( index, revMapper.apply( element ) ); + setter.accept( list ); + } + else + { + getter.get().add( index, revMapper.apply( element ) ); + } + } + + @Override + public T remove( int index ) + { + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.remove( index ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().remove( index ) ); + } + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java b/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java new file mode 100644 index 000000000000..00a6dec175d1 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java @@ -0,0 +1,356 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperProperties extends Properties +{ + + final Supplier getter; + final Consumer setter; + + WrapperProperties( Supplier getter, Consumer setter ) + { + this.getter = getter; + this.setter = setter; + } + + @Override + public String getProperty( String key ) + { + return getter.get().getProperty( key ); + } + + @Override + public String getProperty( String key, String defaultValue ) + { + return getter.get().getProperty( key, defaultValue ); + } + + @Override + public Enumeration propertyNames() + { + return getter.get().propertyNames(); + } + + @Override + public Set stringPropertyNames() + { + return getter.get().stringPropertyNames(); + } + + @Override + public void list( PrintStream out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void list( PrintWriter out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean isEmpty() + { + return getter.get().isEmpty(); + } + + @Override + public Enumeration keys() + { + return getter.get().keys(); + } + + @Override + public Enumeration elements() + { + return getter.get().elements(); + } + + @Override + public boolean contains( Object value ) + { + return getter.get().contains( value ); + } + + @Override + public boolean containsValue( Object value ) + { + return getter.get().containsValue( value ); + } + + @Override + public boolean containsKey( Object key ) + { + return getter.get().containsKey( key ); + } + + @Override + public Object get( Object key ) + { + return getter.get().get( key ); + } + + @Override + public synchronized String toString() + { + return getter.get().toString(); + } + + @Override + public Set keySet() + { + return getter.get().keySet(); + } + + @Override + public Collection values() + { + return getter.get().values(); + } + + @Override + public Set> entrySet() + { + return getter.get().entrySet(); + } + + @Override + public synchronized boolean equals( Object o ) + { + if ( o instanceof WrapperProperties ) + { + o = ( (WrapperProperties) o ).getter.get(); + } + return getter.get().equals( o ); + } + + @Override + public synchronized int hashCode() + { + return getter.get().hashCode(); + } + + @Override + public Object getOrDefault( Object key, Object defaultValue ) + { + return getter.get().getOrDefault( key, defaultValue ); + } + + @Override + public synchronized void forEach( BiConsumer action ) + { + getter.get().forEach( action ); + } + + interface WriteOp + { + T perform( Properties props ); + } + + interface WriteOpVoid + { + void perform( Properties props ); + } + + private T writeOperation( WriteOp runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + T ret = runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + return ret; + } + + private void writeOperationVoid( WriteOpVoid runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + } + + @Override + public synchronized Object setProperty( String key, String value ) + { + return writeOperation( p -> p.setProperty( key, value ) ); + } + + @Override + public synchronized Object put( Object key, Object value ) + { + return writeOperation( p -> p.put( key, value ) ); + } + + @Override + public synchronized Object remove( Object key ) + { + return writeOperation( p -> p.remove( key ) ); + } + + @Override + public synchronized void putAll( Map t ) + { + writeOperationVoid( p -> p.putAll( t ) ); + } + + @Override + public synchronized void clear() + { + writeOperationVoid( Properties::clear ); + } + + @Override + public synchronized void replaceAll( BiFunction function ) + { + writeOperationVoid( p -> p.replaceAll( function ) ); + } + + @Override + public synchronized Object putIfAbsent( Object key, Object value ) + { + return writeOperation( p -> p.putIfAbsent( key, value ) ); + } + + @Override + public synchronized boolean remove( Object key, Object value ) + { + return writeOperation( p -> p.remove( key, value ) ); + } + + @Override + public synchronized boolean replace( Object key, Object oldValue, Object newValue ) + { + return writeOperation( p -> p.replace( key, oldValue, newValue ) ); + } + + @Override + public synchronized Object replace( Object key, Object value ) + { + return writeOperation( p -> p.replace( key, value ) ); + } + + @Override + public synchronized Object computeIfAbsent( Object key, Function mappingFunction ) + { + return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) ); + } + + @Override + public synchronized Object computeIfPresent( Object key, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) ); + } + + @Override + public synchronized Object compute( Object key, BiFunction remappingFunction ) + { + return writeOperation( p -> p.compute( key, remappingFunction ) ); + } + + @Override + public synchronized Object merge( Object key, Object value, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.merge( key, value, remappingFunction ) ); + } + + @Override + public synchronized void load( Reader reader ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void load( InputStream inStream ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void save( OutputStream out, String comments ) + { + getter.get().save( out, comments ); + } + + @Override + public void store( Writer writer, String comments ) throws IOException + { + getter.get().store( writer, comments ); + } + + @Override + public void store( OutputStream out, String comments ) throws IOException + { + getter.get().store( out, comments ); + } + + @Override + public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment ) throws IOException + { + getter.get().storeToXML( os, comment ); + } + + @Override + public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException + { + getter.get().storeToXML( os, comment, encoding ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java new file mode 100644 index 000000000000..95c8c6e70e89 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java @@ -0,0 +1,166 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import org.apache.maven.model.Model; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class MavenXpp3Reader +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public MavenXpp3Reader() + { + this( ( source, fieldName ) -> source ); + } + + public MavenXpp3Reader( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities + ? new MXParser( EntityReplacementMap.defaultEntityReplacementMap ) : new MXParser(); + parser.setInput( reader ); + return read( parser, strict ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + org.apache.maven.model.v4.MavenXpp3Reader reader = contentTransformer != null + ? new org.apache.maven.model.v4.MavenXpp3Reader( contentTransformer::transform ) + : new org.apache.maven.model.v4.MavenXpp3Reader(); + reader.setAddDefaultEntities( addDefaultEntities ); + org.apache.maven.api.model.Model model = reader.read( parser, strict ); + return new Model( model ); + } //-- Model read( XmlPullParser, boolean ) + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java new file mode 100644 index 000000000000..9fb37d0494cf --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java @@ -0,0 +1,169 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import org.apache.maven.model.InputSource; +import org.apache.maven.model.Model; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class MavenXpp3ReaderEx +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public MavenXpp3ReaderEx() + { + this( ( source, fieldName ) -> source ); + } + + public MavenXpp3ReaderEx( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities + ? new MXParser( EntityReplacementMap.defaultEntityReplacementMap ) : new MXParser( ); + parser.setInput( reader ); + return read( parser, strict, source ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, InputSource source ) + throws IOException, XmlPullParserException + { + return read( reader, true, source ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict, source ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, InputSource source ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), source ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + org.apache.maven.model.v4.MavenXpp3ReaderEx reader = contentTransformer != null + ? new org.apache.maven.model.v4.MavenXpp3ReaderEx( contentTransformer::transform ) + : new org.apache.maven.model.v4.MavenXpp3ReaderEx(); + reader.setAddDefaultEntities( addDefaultEntities ); + org.apache.maven.api.model.Model model = reader.read( parser, strict, + new org.apache.maven.api.model.InputSource( source.getModelId(), source.getLocation() ) ); + return new Model( model ); + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java new file mode 100644 index 000000000000..97e8ad41ce62 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java @@ -0,0 +1,83 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import org.apache.maven.model.Model; + +public class MavenXpp3Writer +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( Writer writer, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3Writer xw = new org.apache.maven.model.v4.MavenXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( writer, model.getDelegate() ); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3Writer xw = new org.apache.maven.model.v4.MavenXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( stream, model.getDelegate() ); + } //-- void write( OutputStream, Model ) + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java new file mode 100644 index 000000000000..ad6842564b2a --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java @@ -0,0 +1,108 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import org.apache.maven.model.InputLocation; +import org.apache.maven.model.Model; + +public class MavenXpp3WriterEx +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field fileComment. + */ + private String fileComment = null; + + /** + * Field stringFormatter. + */ + protected InputLocation.StringFormatter stringFormatter; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method setStringFormatter. + * + * @param stringFormatter + */ + public void setStringFormatter( InputLocation.StringFormatter stringFormatter ) + { + this.stringFormatter = stringFormatter; + } //-- void setStringFormatter( InputLocation.StringFormatter ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( Writer writer, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3WriterEx xw = new org.apache.maven.model.v4.MavenXpp3WriterEx(); + xw.setFileComment( fileComment ); + xw.setStringFormatter( stringFormatter != null ? new org.apache.maven.api.model.InputLocation.StringFormatter() + { + @Override + public String toString( org.apache.maven.api.model.InputLocation location ) + { + return stringFormatter.toString( new InputLocation( location ) ); + } + } : null ); + xw.write( writer, model.getDelegate() ); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3WriterEx xw = new org.apache.maven.model.v4.MavenXpp3WriterEx(); + xw.setFileComment( fileComment ); + xw.write( stream, model.getDelegate() ); + } //-- void write( OutputStream, Model ) + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java b/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java deleted file mode 100644 index 2ac6fbf973a0..000000000000 --- a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java +++ /dev/null @@ -1,2802 +0,0 @@ -package org.apache.maven.model.merge; - -/* - * 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. - */ - -import java.io.ObjectStreamException; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.maven.model.Activation; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.ConfigurationContainer; -import org.apache.maven.model.Contributor; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.DeploymentRepository; -import org.apache.maven.model.Developer; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Extension; -import org.apache.maven.model.FileSet; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.License; -import org.apache.maven.model.MailingList; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Notifier; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Parent; -import org.apache.maven.model.PatternSet; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginConfiguration; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Relocation; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryBase; -import org.apache.maven.model.RepositoryPolicy; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; -import org.codehaus.plexus.util.xml.Xpp3Dom; - -/** - * This is a hand-crafted prototype of the default model merger that should eventually be generated by Modello by a new - * Java plugin. Code structure to merge source (read-only) object into the target object is:
    - *
  • mergeClassname( Classname target, Classname source, boolean sourceDominant, - * Map<Object, Object> context ) for each model class
  • - *
  • mergeClassname_FieldName( Classname target, Classname source, boolean - * sourceDominant, Map<Object, Object> context ) for each field of each model class
  • - *
  • Object getClassnameKey( Classname classname ) - * for each class that is used in a list
  • - *
- * Code is written like it could be generated, with default behaviour to be overridden when necessary. - * This is particularly the case for Object getClassnameKey( Classname classname ) - * method, which by default return the object itself and is expected to be overridden to calculate better suited key - * value. - * - * @author Benjamin Bentmann - */ -@SuppressWarnings( { "checkstyle:methodname" } ) -public class ModelMerger -{ - - /** - * Merges the specified source object into the given target object. - * - * @param target The target object whose existing contents should be merged with the source, must not be - * null. - * @param source The (read-only) source object that should be merged into the target object, may be - * null. - * @param sourceDominant A flag indicating whether either the target object or the source object provides the - * dominant data. - * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific - * information along, may be null. - */ - public void merge( Model target, Model source, boolean sourceDominant, Map hints ) - { - Objects.requireNonNull( target, "target cannot be null" ); - - if ( source == null ) - { - return; - } - - Map context = new HashMap<>(); - if ( hints != null ) - { - context.putAll( hints ); - } - - mergeModel( target, source, sourceDominant, context ); - } - - protected void mergeModel( Model target, Model source, boolean sourceDominant, Map context ) - { - mergeModelBase( target, source, sourceDominant, context ); - - mergeModel_ChildProjectUrlInheritAppendPath( target, source, sourceDominant, context ); - mergeModel_ModelVersion( target, source, sourceDominant, context ); - mergeModel_Parent( target, source, sourceDominant, context ); - mergeModel_GroupId( target, source, sourceDominant, context ); - mergeModel_ArtifactId( target, source, sourceDominant, context ); - mergeModel_Version( target, source, sourceDominant, context ); - mergeModel_Packaging( target, source, sourceDominant, context ); - mergeModel_Name( target, source, sourceDominant, context ); - mergeModel_Description( target, source, sourceDominant, context ); - mergeModel_Url( target, source, sourceDominant, context ); - mergeModel_InceptionYear( target, source, sourceDominant, context ); - mergeModel_Organization( target, source, sourceDominant, context ); - mergeModel_Licenses( target, source, sourceDominant, context ); - mergeModel_MailingLists( target, source, sourceDominant, context ); - mergeModel_Developers( target, source, sourceDominant, context ); - mergeModel_Contributors( target, source, sourceDominant, context ); - mergeModel_IssueManagement( target, source, sourceDominant, context ); - mergeModel_Scm( target, source, sourceDominant, context ); - mergeModel_CiManagement( target, source, sourceDominant, context ); - mergeModel_Prerequisites( target, source, sourceDominant, context ); - mergeModel_Build( target, source, sourceDominant, context ); - mergeModel_Profiles( target, source, sourceDominant, context ); - } - - protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getModelVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getModelVersion() == null ) - { - target.setModelVersion( src ); - target.setLocation( "modelVersion", source.getLocation( "modelVersion" ) ); - } - } - } - - protected void mergeModel_Parent( Model target, Model source, boolean sourceDominant, Map context ) - { - Parent src = source.getParent(); - if ( src != null ) - { - Parent tgt = target.getParent(); - if ( tgt == null ) - { - tgt = new Parent(); - tgt.setRelativePath( null ); - target.setParent( tgt ); - } - mergeParent( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_GroupId( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeModel_ChildProjectUrlInheritAppendPath( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getChildProjectUrlInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildProjectUrlInheritAppendPath() == null ) - { - target.setChildProjectUrlInheritAppendPath( src ); - target.setLocation( "child.project.url.inherit.append.path", - source.getLocation( "child.project.url.inherit.append.path" ) ); - } - } - } - - protected void mergeModel_Version( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeModel_Packaging( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getPackaging(); - if ( src != null ) - { - if ( sourceDominant || target.getPackaging() == null ) - { - target.setPackaging( src ); - target.setLocation( "packaging", source.getLocation( "packaging" ) ); - } - } - } - - protected void mergeModel_Name( Model target, Model source, boolean sourceDominant, Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeModel_Description( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getDescription(); - if ( src != null ) - { - if ( sourceDominant || target.getDescription() == null ) - { - target.setDescription( src ); - target.setLocation( "description", source.getLocation( "description" ) ); - } - } - } - - protected void mergeModel_Url( Model target, Model source, boolean sourceDominant, Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeModel_InceptionYear( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getInceptionYear(); - if ( src != null ) - { - if ( sourceDominant || target.getInceptionYear() == null ) - { - target.setInceptionYear( src ); - target.setLocation( "inceptionYear", source.getLocation( "inceptionYear" ) ); - } - } - } - - protected void mergeModel_Organization( Model target, Model source, boolean sourceDominant, - Map context ) - { - Organization src = source.getOrganization(); - if ( src != null ) - { - Organization tgt = target.getOrganization(); - if ( tgt == null ) - { - tgt = new Organization(); - target.setOrganization( tgt ); - } - mergeOrganization( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setLicenses( merge( target.getLicenses(), source.getLicenses(), - sourceDominant, getLicenseKey() ) ); - } - - protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setMailingLists( merge( target.getMailingLists(), source.getMailingLists(), - sourceDominant, getMailingListKey() ) ); - } - - protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setDevelopers( merge( target.getDevelopers(), source.getDevelopers(), - sourceDominant, getDeveloperKey() ) ); - } - - protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setContributors( merge( target.getContributors(), source.getContributors(), - sourceDominant, getContributorKey() ) ); - } - - protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant, - Map context ) - { - IssueManagement src = source.getIssueManagement(); - if ( src != null ) - { - IssueManagement tgt = target.getIssueManagement(); - if ( tgt == null ) - { - tgt = new IssueManagement(); - target.setIssueManagement( tgt ); - } - mergeIssueManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Scm( Model target, Model source, boolean sourceDominant, Map context ) - { - Scm src = source.getScm(); - if ( src != null ) - { - Scm tgt = target.getScm(); - if ( tgt == null ) - { - tgt = new Scm(); - tgt.setTag( null ); - target.setScm( tgt ); - } - mergeScm( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_CiManagement( Model target, Model source, boolean sourceDominant, - Map context ) - { - CiManagement src = source.getCiManagement(); - if ( src != null ) - { - CiManagement tgt = target.getCiManagement(); - if ( tgt == null ) - { - tgt = new CiManagement(); - target.setCiManagement( tgt ); - } - mergeCiManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant, - Map context ) - { - Prerequisites src = source.getPrerequisites(); - if ( src != null ) - { - Prerequisites tgt = target.getPrerequisites(); - if ( tgt == null ) - { - tgt = new Prerequisites(); - tgt.setMaven( null ); - target.setPrerequisites( tgt ); - } - mergePrerequisites( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Build( Model target, Model source, boolean sourceDominant, Map context ) - { - Build src = source.getBuild(); - if ( src != null ) - { - Build tgt = target.getBuild(); - if ( tgt == null ) - { - tgt = new Build(); - target.setBuild( tgt ); - } - mergeBuild( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setProfiles( merge( target.getProfiles(), source.getProfiles(), - sourceDominant, getProfileKey() ) ); - } - - protected void mergeModelBase( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - mergeModelBase_DistributionManagement( target, source, sourceDominant, context ); - mergeModelBase_Modules( target, source, sourceDominant, context ); - mergeModelBase_Repositories( target, source, sourceDominant, context ); - mergeModelBase_PluginRepositories( target, source, sourceDominant, context ); - mergeModelBase_Dependencies( target, source, sourceDominant, context ); - mergeModelBase_Reporting( target, source, sourceDominant, context ); - mergeModelBase_DependencyManagement( target, source, sourceDominant, context ); - mergeModelBase_Properties( target, source, sourceDominant, context ); - } - - protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setModules( merge( target.getModules(), source.getModules(), sourceDominant, e -> e ) ); - } - - protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setDependencies( merge( target.getDependencies(), source.getDependencies(), - sourceDominant, getDependencyKey() ) ); - } - - protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setRepositories( merge( target.getRepositories(), source.getRepositories(), - sourceDominant, getRepositoryKey() ) ); - } - - protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setPluginRepositories( merge( target.getPluginRepositories(), source.getPluginRepositories(), - sourceDominant, getRepositoryKey() ) ); - } - - protected void mergeModelBase_DistributionManagement( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - DistributionManagement src = source.getDistributionManagement(); - if ( src != null ) - { - DistributionManagement tgt = target.getDistributionManagement(); - if ( tgt == null ) - { - tgt = new DistributionManagement(); - target.setDistributionManagement( tgt ); - } - mergeDistributionManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModelBase_Reporting( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - Reporting src = source.getReporting(); - if ( src != null ) - { - Reporting tgt = target.getReporting(); - if ( tgt == null ) - { - tgt = new Reporting(); - target.setReporting( tgt ); - } - mergeReporting( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModelBase_DependencyManagement( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - DependencyManagement src = source.getDependencyManagement(); - if ( src != null ) - { - DependencyManagement tgt = target.getDependencyManagement(); - if ( tgt == null ) - { - tgt = new DependencyManagement(); - target.setDependencyManagement( tgt ); - } - mergeDependencyManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModelBase_Properties( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - Properties merged = new Properties(); - if ( sourceDominant ) - { - merged.putAll( target.getProperties() ); - merged.putAll( source.getProperties() ); - } - else - { - merged.putAll( source.getProperties() ); - merged.putAll( target.getProperties() ); - } - target.setProperties( merged ); - target.setLocation( "properties", InputLocation.merge( target.getLocation( "properties" ), - source.getLocation( "properties" ), sourceDominant ) ); - } - - protected void mergeDistributionManagement( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) - { - mergeDistributionManagement_Repository( target, source, sourceDominant, context ); - mergeDistributionManagement_SnapshotRepository( target, source, sourceDominant, context ); - mergeDistributionManagement_Site( target, source, sourceDominant, context ); - mergeDistributionManagement_Status( target, source, sourceDominant, context ); - mergeDistributionManagement_DownloadUrl( target, source, sourceDominant, context ); - } - - protected void mergeDistributionManagement_Repository( DistributionManagement target, - DistributionManagement source, boolean sourceDominant, - Map context ) - { - DeploymentRepository src = source.getRepository(); - if ( src != null ) - { - DeploymentRepository tgt = target.getRepository(); - if ( tgt == null ) - { - tgt = new DeploymentRepository(); - target.setRepository( tgt ); - } - mergeDeploymentRepository( tgt, src, sourceDominant, context ); - } - } - - protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target, - DistributionManagement source, - boolean sourceDominant, - Map context ) - { - DeploymentRepository src = source.getSnapshotRepository(); - if ( src != null ) - { - DeploymentRepository tgt = target.getSnapshotRepository(); - if ( tgt == null ) - { - tgt = new DeploymentRepository(); - target.setSnapshotRepository( tgt ); - } - mergeDeploymentRepository( tgt, src, sourceDominant, context ); - } - } - - protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) - { - Site src = source.getSite(); - if ( src != null ) - { - Site tgt = target.getSite(); - if ( tgt == null ) - { - tgt = new Site(); - target.setSite( tgt ); - } - mergeSite( tgt, src, sourceDominant, context ); - } - } - - protected void mergeDistributionManagement_Status( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) - { - String src = source.getStatus(); - if ( src != null ) - { - if ( sourceDominant || target.getStatus() == null ) - { - target.setStatus( src ); - target.setLocation( "status", source.getLocation( "status" ) ); - } - } - } - - protected void mergeDistributionManagement_DownloadUrl( DistributionManagement target, - DistributionManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getDownloadUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getDownloadUrl() == null ) - { - target.setDownloadUrl( src ); - target.setLocation( "downloadUrl", source.getLocation( "downloadUrl" ) ); - } - } - } - - protected void mergeRelocation( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - mergeRelocation_GroupId( target, source, sourceDominant, context ); - mergeRelocation_ArtifactId( target, source, sourceDominant, context ); - mergeRelocation_Version( target, source, sourceDominant, context ); - mergeRelocation_Message( target, source, sourceDominant, context ); - } - - protected void mergeRelocation_GroupId( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeRelocation_ArtifactId( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeRelocation_Version( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeRelocation_Message( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getMessage(); - if ( src != null ) - { - if ( sourceDominant || target.getMessage() == null ) - { - target.setMessage( src ); - target.setLocation( "message", source.getLocation( "message" ) ); - } - } - } - - protected void mergeDeploymentRepository( DeploymentRepository target, DeploymentRepository source, - boolean sourceDominant, Map context ) - { - mergeRepository( target, source, sourceDominant, context ); - mergeDeploymentRepository_UniqueVersion( target, source, sourceDominant, context ); - } - - protected void mergeDeploymentRepository_UniqueVersion( DeploymentRepository target, DeploymentRepository source, - boolean sourceDominant, Map context ) - { - if ( sourceDominant ) - { - target.setUniqueVersion( source.isUniqueVersion() ); - target.setLocation( "uniqueVersion", source.getLocation( "uniqueVersion" ) ); - } - } - - protected void mergeSite( Site target, Site source, boolean sourceDominant, Map context ) - { - mergeSite_ChildSiteUrlInheritAppendPath( target, source, sourceDominant, context ); - mergeSite_Id( target, source, sourceDominant, context ); - mergeSite_Name( target, source, sourceDominant, context ); - mergeSite_Url( target, source, sourceDominant, context ); - } - - protected void mergeSite_ChildSiteUrlInheritAppendPath( Site target, Site source, boolean sourceDominant, - Map context ) - { - String src = source.getChildSiteUrlInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildSiteUrlInheritAppendPath() == null ) - { - target.setChildSiteUrlInheritAppendPath( src ); - target.setLocation( "child.site.url.inherit.append.path", - source.getLocation( "child.site.url.inherit.append.path" ) ); - } - } - } - - protected void mergeSite_Id( Site target, Site source, boolean sourceDominant, Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeSite_Name( Site target, Site source, boolean sourceDominant, Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeRepository( Repository target, Repository source, boolean sourceDominant, - Map context ) - { - mergeRepositoryBase( target, source, sourceDominant, context ); - mergeRepository_Releases( target, source, sourceDominant, context ); - mergeRepository_Snapshots( target, source, sourceDominant, context ); - } - - protected void mergeRepository_Releases( Repository target, Repository source, boolean sourceDominant, - Map context ) - { - RepositoryPolicy src = source.getReleases(); - if ( src != null ) - { - RepositoryPolicy tgt = target.getReleases(); - if ( tgt == null ) - { - tgt = new RepositoryPolicy(); - target.setReleases( tgt ); - } - mergeRepositoryPolicy( tgt, src, sourceDominant, context ); - } - } - - protected void mergeRepository_Snapshots( Repository target, Repository source, boolean sourceDominant, - Map context ) - { - RepositoryPolicy src = source.getSnapshots(); - if ( src != null ) - { - RepositoryPolicy tgt = target.getSnapshots(); - if ( tgt == null ) - { - tgt = new RepositoryPolicy(); - target.setSnapshots( tgt ); - } - mergeRepositoryPolicy( tgt, src, sourceDominant, context ); - } - } - - protected void mergeRepositoryBase( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - mergeRepositoryBase_Id( target, source, sourceDominant, context ); - mergeRepositoryBase_Name( target, source, sourceDominant, context ); - mergeRepositoryBase_Url( target, source, sourceDominant, context ); - mergeRepositoryBase_Layout( target, source, sourceDominant, context ); - } - - protected void mergeRepositoryBase_Id( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeRepositoryBase_Url( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeRepositoryBase_Name( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeRepositoryBase_Layout( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getLayout(); - if ( src != null ) - { - if ( sourceDominant || target.getLayout() == null ) - { - target.setLayout( src ); - target.setLocation( "layout", source.getLocation( "layout" ) ); - } - } - } - - protected void mergeRepositoryPolicy( RepositoryPolicy target, RepositoryPolicy source, boolean sourceDominant, - Map context ) - { - mergeRepositoryPolicy_Enabled( target, source, sourceDominant, context ); - mergeRepositoryPolicy_UpdatePolicy( target, source, sourceDominant, context ); - mergeRepositoryPolicy_ChecksumPolicy( target, source, sourceDominant, context ); - } - - protected void mergeRepositoryPolicy_Enabled( RepositoryPolicy target, RepositoryPolicy source, - boolean sourceDominant, Map context ) - { - String src = source.getEnabled(); - if ( src != null ) - { - if ( sourceDominant || target.getEnabled() == null ) - { - target.setEnabled( src ); - target.setLocation( "enabled", source.getLocation( "enabled" ) ); - } - } - } - - protected void mergeRepositoryPolicy_UpdatePolicy( RepositoryPolicy target, RepositoryPolicy source, - boolean sourceDominant, Map context ) - { - String src = source.getUpdatePolicy(); - if ( src != null ) - { - if ( sourceDominant || target.getUpdatePolicy() == null ) - { - target.setUpdatePolicy( src ); - target.setLocation( "updatePolicy", source.getLocation( "updatePolicy" ) ); - } - } - } - - protected void mergeRepositoryPolicy_ChecksumPolicy( RepositoryPolicy target, RepositoryPolicy source, - boolean sourceDominant, Map context ) - { - String src = source.getChecksumPolicy(); - if ( src != null ) - { - if ( sourceDominant || target.getChecksumPolicy() == null ) - { - target.setChecksumPolicy( src ); - target.setLocation( "checksumPolicy", source.getLocation( "checksumPolicy" ) ); - } - } - } - - protected void mergeDependency( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - mergeDependency_GroupId( target, source, sourceDominant, context ); - mergeDependency_ArtifactId( target, source, sourceDominant, context ); - mergeDependency_Version( target, source, sourceDominant, context ); - mergeDependency_Type( target, source, sourceDominant, context ); - mergeDependency_Classifier( target, source, sourceDominant, context ); - mergeDependency_Scope( target, source, sourceDominant, context ); - mergeDependency_SystemPath( target, source, sourceDominant, context ); - mergeDependency_Optional( target, source, sourceDominant, context ); - mergeDependency_Exclusions( target, source, sourceDominant, context ); - } - - protected void mergeDependency_GroupId( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeDependency_ArtifactId( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeDependency_Version( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeDependency_Type( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getType(); - if ( src != null ) - { - if ( sourceDominant || target.getType() == null ) - { - target.setType( src ); - target.setLocation( "type", source.getLocation( "type" ) ); - } - } - } - - protected void mergeDependency_Classifier( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getClassifier(); - if ( src != null ) - { - if ( sourceDominant || target.getClassifier() == null ) - { - target.setClassifier( src ); - target.setLocation( "classifier", source.getLocation( "classifier" ) ); - } - } - } - - protected void mergeDependency_Scope( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getScope(); - if ( src != null ) - { - if ( sourceDominant || target.getScope() == null ) - { - target.setScope( src ); - target.setLocation( "scope", source.getLocation( "scope" ) ); - } - } - } - - protected void mergeDependency_SystemPath( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getSystemPath(); - if ( src != null ) - { - if ( sourceDominant || target.getSystemPath() == null ) - { - target.setSystemPath( src ); - target.setLocation( "systemPath", source.getLocation( "systemPath" ) ); - } - } - } - - protected void mergeDependency_Optional( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getOptional(); - if ( src != null ) - { - if ( sourceDominant || target.getOptional() == null ) - { - target.setOptional( src ); - target.setLocation( "optional", source.getLocation( "optional" ) ); - } - } - } - - protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - target.setExclusions( merge( target.getExclusions(), source.getExclusions(), - sourceDominant, getExclusionKey() ) ); - } - - protected void mergeExclusion( Exclusion target, Exclusion source, boolean sourceDominant, - Map context ) - { - mergeExclusion_GroupId( target, source, sourceDominant, context ); - mergeExclusion_ArtifactId( target, source, sourceDominant, context ); - } - - protected void mergeExclusion_GroupId( Exclusion target, Exclusion source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeExclusion_ArtifactId( Exclusion target, Exclusion source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeReporting( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - mergeReporting_OutputDirectory( target, source, sourceDominant, context ); - mergeReporting_ExcludeDefaults( target, source, sourceDominant, context ); - mergeReporting_Plugins( target, source, sourceDominant, context ); - } - - protected void mergeReporting_OutputDirectory( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - String src = source.getOutputDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getOutputDirectory() == null ) - { - target.setOutputDirectory( src ); - target.setLocation( "outputDirectory", source.getLocation( "outputDirectory" ) ); - } - } - } - - protected void mergeReporting_ExcludeDefaults( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - String src = source.getExcludeDefaults(); - if ( src != null ) - { - if ( sourceDominant || target.getExcludeDefaults() == null ) - { - target.setExcludeDefaults( src ); - target.setLocation( "excludeDefaults", source.getLocation( "excludeDefaults" ) ); - } - } - } - - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - target.setPlugins( merge( target.getPlugins(), source.getPlugins(), - sourceDominant, getReportPluginKey() ) ); - } - - protected void mergeReportPlugin( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergeReportPlugin_GroupId( target, source, sourceDominant, context ); - mergeReportPlugin_ArtifactId( target, source, sourceDominant, context ); - mergeReportPlugin_Version( target, source, sourceDominant, context ); - mergeReportPlugin_ReportSets( target, source, sourceDominant, context ); - } - - protected void mergeReportPlugin_GroupId( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeReportPlugin_ArtifactId( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeReportPlugin_Version( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - target.setReportSets( merge( target.getReportSets(), source.getReportSets(), - sourceDominant, getReportSetKey() ) ); - } - - protected void mergeReportSet( ReportSet target, ReportSet source, boolean sourceDominant, - Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergeReportSet_Id( target, source, sourceDominant, context ); - mergeReportSet_Reports( target, source, sourceDominant, context ); - } - - protected void mergeReportSet_Id( ReportSet target, ReportSet source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeReportSet_Reports( ReportSet target, ReportSet source, boolean sourceDominant, - Map context ) - { - target.setReports( merge( target.getReports(), source.getReports(), sourceDominant, e -> e ) ); - } - - protected void mergeDependencyManagement( DependencyManagement target, DependencyManagement source, - boolean sourceDominant, Map context ) - { - mergeDependencyManagement_Dependencies( target, source, sourceDominant, context ); - } - - protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source, - boolean sourceDominant, Map context ) - { - target.setDependencies( merge( target.getDependencies(), source.getDependencies(), - sourceDominant, getDependencyKey() ) ); - } - - protected void mergeParent( Parent target, Parent source, boolean sourceDominant, Map context ) - { - mergeParent_GroupId( target, source, sourceDominant, context ); - mergeParent_ArtifactId( target, source, sourceDominant, context ); - mergeParent_Version( target, source, sourceDominant, context ); - mergeParent_RelativePath( target, source, sourceDominant, context ); - } - - protected void mergeParent_GroupId( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeParent_ArtifactId( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeParent_Version( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeParent_RelativePath( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getRelativePath(); - if ( src != null ) - { - if ( sourceDominant || target.getRelativePath() == null ) - { - target.setRelativePath( src ); - target.setLocation( "relativePath", source.getLocation( "relativePath" ) ); - } - } - } - - protected void mergeOrganization( Organization target, Organization source, boolean sourceDominant, - Map context ) - { - mergeOrganization_Name( target, source, sourceDominant, context ); - mergeOrganization_Url( target, source, sourceDominant, context ); - } - - protected void mergeOrganization_Name( Organization target, Organization source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeOrganization_Url( Organization target, Organization source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeLicense( License target, License source, boolean sourceDominant, Map context ) - { - mergeLicense_Name( target, source, sourceDominant, context ); - mergeLicense_Url( target, source, sourceDominant, context ); - mergeLicense_Distribution( target, source, sourceDominant, context ); - mergeLicense_Comments( target, source, sourceDominant, context ); - } - - protected void mergeLicense_Name( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeLicense_Url( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeLicense_Distribution( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getDistribution(); - if ( src != null ) - { - if ( sourceDominant || target.getDistribution() == null ) - { - target.setDistribution( src ); - target.setLocation( "distribution", source.getLocation( "distribution" ) ); - } - } - } - - protected void mergeLicense_Comments( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getComments(); - if ( src != null ) - { - if ( sourceDominant || target.getComments() == null ) - { - target.setComments( src ); - target.setLocation( "comments", source.getLocation( "comments" ) ); - } - } - } - - protected void mergeMailingList( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - mergeMailingList_Name( target, source, sourceDominant, context ); - mergeMailingList_Subscribe( target, source, sourceDominant, context ); - mergeMailingList_Unsubscribe( target, source, sourceDominant, context ); - mergeMailingList_Post( target, source, sourceDominant, context ); - mergeMailingList_OtherArchives( target, source, sourceDominant, context ); - } - - protected void mergeMailingList_Name( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeMailingList_Subscribe( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getSubscribe(); - if ( src != null ) - { - if ( sourceDominant || target.getSubscribe() == null ) - { - target.setSubscribe( src ); - target.setLocation( "subscribe", source.getLocation( "subscribe" ) ); - } - } - } - - protected void mergeMailingList_Unsubscribe( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getUnsubscribe(); - if ( src != null ) - { - if ( sourceDominant || target.getUnsubscribe() == null ) - { - target.setUnsubscribe( src ); - target.setLocation( "unsubscribe", source.getLocation( "unsubscribe" ) ); - } - } - } - - protected void mergeMailingList_Post( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getPost(); - if ( src != null ) - { - if ( sourceDominant || target.getPost() == null ) - { - target.setPost( src ); - target.setLocation( "post", source.getLocation( "post" ) ); - } - } - } - - protected void mergeMailingList_Archive( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getArchive(); - if ( src != null ) - { - if ( sourceDominant || target.getArchive() == null ) - { - target.setArchive( src ); - target.setLocation( "archive", source.getLocation( "archive" ) ); - } - } - } - - protected void mergeMailingList_OtherArchives( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - target.setOtherArchives( merge( target.getOtherArchives(), - source.getOtherArchives(), - sourceDominant, - e -> e ) ); - } - - protected void mergeDeveloper( Developer target, Developer source, boolean sourceDominant, - Map context ) - { - mergeContributor( target, source, sourceDominant, context ); - mergeDeveloper_Id( target, source, sourceDominant, context ); - } - - protected void mergeDeveloper_Id( Developer target, Developer source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeContributor( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - mergeContributor_Name( target, source, sourceDominant, context ); - mergeContributor_Email( target, source, sourceDominant, context ); - mergeContributor_Url( target, source, sourceDominant, context ); - mergeContributor_Organization( target, source, sourceDominant, context ); - mergeContributor_OrganizationUrl( target, source, sourceDominant, context ); - mergeContributor_Timezone( target, source, sourceDominant, context ); - mergeContributor_Roles( target, source, sourceDominant, context ); - mergeContributor_Properties( target, source, sourceDominant, context ); - } - - protected void mergeContributor_Name( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeContributor_Email( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getEmail(); - if ( src != null ) - { - if ( sourceDominant || target.getEmail() == null ) - { - target.setEmail( src ); - target.setLocation( "email", source.getLocation( "email" ) ); - } - } - } - - protected void mergeContributor_Url( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeContributor_Organization( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getOrganization(); - if ( src != null ) - { - if ( sourceDominant || target.getOrganization() == null ) - { - target.setOrganization( src ); - target.setLocation( "organization", source.getLocation( "organization" ) ); - } - } - } - - protected void mergeContributor_OrganizationUrl( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getOrganizationUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getOrganizationUrl() == null ) - { - target.setOrganizationUrl( src ); - target.setLocation( "organizationUrl", source.getLocation( "organizationUrl" ) ); - } - } - } - - protected void mergeContributor_Timezone( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getTimezone(); - if ( src != null ) - { - if ( sourceDominant || target.getTimezone() == null ) - { - target.setTimezone( src ); - target.setLocation( "timezone", source.getLocation( "timezone" ) ); - } - } - } - - protected void mergeContributor_Roles( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - target.setRoles( merge( target.getRoles(), source.getRoles(), sourceDominant, e -> e ) ); - } - - protected void mergeContributor_Properties( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - Properties merged = new Properties(); - if ( sourceDominant ) - { - merged.putAll( target.getProperties() ); - merged.putAll( source.getProperties() ); - } - else - { - merged.putAll( source.getProperties() ); - merged.putAll( target.getProperties() ); - } - target.setProperties( merged ); - target.setLocation( "properties", InputLocation.merge( target.getLocation( "properties" ), - source.getLocation( "properties" ), sourceDominant ) ); - } - - protected void mergeIssueManagement( IssueManagement target, IssueManagement source, boolean sourceDominant, - Map context ) - { - mergeIssueManagement_Url( target, source, sourceDominant, context ); - mergeIssueManagement_System( target, source, sourceDominant, context ); - } - - protected void mergeIssueManagement_System( IssueManagement target, IssueManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getSystem(); - if ( src != null ) - { - if ( sourceDominant || target.getSystem() == null ) - { - target.setSystem( src ); - target.setLocation( "system", source.getLocation( "system" ) ); - } - } - } - - protected void mergeIssueManagement_Url( IssueManagement target, IssueManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeScm( Scm target, Scm source, boolean sourceDominant, Map context ) - { - mergeScm_ChildScmConnectionInheritAppendPath( target, source, sourceDominant, context ); - mergeScm_ChildScmDeveloperConnectionInheritAppendPath( target, source, sourceDominant, context ); - mergeScm_ChildScmUrlInheritAppendPath( target, source, sourceDominant, context ); - mergeScm_Url( target, source, sourceDominant, context ); - mergeScm_Connection( target, source, sourceDominant, context ); - mergeScm_DeveloperConnection( target, source, sourceDominant, context ); - mergeScm_Tag( target, source, sourceDominant, context ); - } - - protected void mergeScm_ChildScmConnectionInheritAppendPath( Scm target, Scm source, boolean sourceDominant, - Map context ) - { - String src = source.getChildScmConnectionInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildScmConnectionInheritAppendPath() == null ) - { - target.setChildScmConnectionInheritAppendPath( src ); - target.setLocation( "child.scm.connection.inherit.append.path", - source.getLocation( "child.scm.connection.inherit.append.path" ) ); - } - } - } - - protected void mergeScm_ChildScmDeveloperConnectionInheritAppendPath( Scm target, Scm source, - boolean sourceDominant, - Map context ) - { - String src = source.getChildScmDeveloperConnectionInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildScmDeveloperConnectionInheritAppendPath() == null ) - { - target.setChildScmDeveloperConnectionInheritAppendPath( src ); - target.setLocation( "child.scm.developerConnection.inherit.append.path", - source.getLocation( "child.scm.developerConnection.inherit.append.path" ) ); - } - } - } - - protected void mergeScm_ChildScmUrlInheritAppendPath( Scm target, Scm source, boolean sourceDominant, - Map context ) - { - String src = source.getChildScmUrlInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildScmUrlInheritAppendPath() == null ) - { - target.setChildScmUrlInheritAppendPath( src ); - target.setLocation( "child.scm.url.inherit.append.path", - source.getLocation( "child.scm.url.inherit.append.path" ) ); - } - } - } - - protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map context ) - { - String src = source.getConnection(); - if ( src != null ) - { - if ( sourceDominant || target.getConnection() == null ) - { - target.setConnection( src ); - target.setLocation( "connection", source.getLocation( "connection" ) ); - } - } - } - - protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant, - Map context ) - { - String src = source.getDeveloperConnection(); - if ( src != null ) - { - if ( sourceDominant || target.getDeveloperConnection() == null ) - { - target.setDeveloperConnection( src ); - target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) ); - } - } - } - - protected void mergeScm_Tag( Scm target, Scm source, boolean sourceDominant, Map context ) - { - String src = source.getTag(); - if ( src != null ) - { - if ( sourceDominant || target.getTag() == null ) - { - target.setTag( src ); - target.setLocation( "tag", source.getLocation( "tag" ) ); - } - } - } - - protected void mergeCiManagement( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - mergeCiManagement_System( target, source, sourceDominant, context ); - mergeCiManagement_Url( target, source, sourceDominant, context ); - mergeCiManagement_Notifiers( target, source, sourceDominant, context ); - } - - protected void mergeCiManagement_System( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getSystem(); - if ( src != null ) - { - if ( sourceDominant || target.getSystem() == null ) - { - target.setSystem( src ); - target.setLocation( "system", source.getLocation( "system" ) ); - } - } - } - - protected void mergeCiManagement_Url( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeCiManagement_Notifiers( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - target.setNotifiers( merge( target.getNotifiers(), source.getNotifiers(), - sourceDominant, getNotifierKey() ) ); - } - - protected void mergeNotifier( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - mergeNotifier_Type( target, source, sourceDominant, context ); - mergeNotifier_Address( target, source, sourceDominant, context ); - mergeNotifier_Configuration( target, source, sourceDominant, context ); - mergeNotifier_SendOnError( target, source, sourceDominant, context ); - mergeNotifier_SendOnFailure( target, source, sourceDominant, context ); - mergeNotifier_SendOnSuccess( target, source, sourceDominant, context ); - mergeNotifier_SendOnWarning( target, source, sourceDominant, context ); - } - - protected void mergeNotifier_Type( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - String src = source.getType(); - if ( src != null ) - { - if ( sourceDominant || target.getType() == null ) - { - target.setType( src ); - } - } - } - - protected void mergeNotifier_Address( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - String src = source.getAddress(); - if ( src != null ) - { - if ( sourceDominant || target.getAddress() == null ) - { - target.setAddress( src ); - } - } - } - - protected void mergeNotifier_Configuration( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - Properties merged = new Properties(); - if ( sourceDominant ) - { - merged.putAll( target.getConfiguration() ); - merged.putAll( source.getConfiguration() ); - } - else - { - merged.putAll( source.getConfiguration() ); - merged.putAll( target.getConfiguration() ); - } - target.setConfiguration( merged ); - } - - protected void mergeNotifier_SendOnError( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnError( source.isSendOnError() ); - } - } - - protected void mergeNotifier_SendOnFailure( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnFailure( source.isSendOnFailure() ); - } - } - - protected void mergeNotifier_SendOnSuccess( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnSuccess( source.isSendOnSuccess() ); - } - } - - protected void mergeNotifier_SendOnWarning( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnWarning( source.isSendOnWarning() ); - } - } - - protected void mergePrerequisites( Prerequisites target, Prerequisites source, boolean sourceDominant, - Map context ) - { - mergePrerequisites_Maven( target, source, sourceDominant, context ); - } - - protected void mergePrerequisites_Maven( Prerequisites target, Prerequisites source, boolean sourceDominant, - Map context ) - { - String src = source.getMaven(); - if ( src != null ) - { - if ( sourceDominant || target.getMaven() == null ) - { - target.setMaven( src ); - target.setLocation( "maven", source.getLocation( "maven" ) ); - } - } - } - - protected void mergeBuild( Build target, Build source, boolean sourceDominant, Map context ) - { - mergeBuildBase( target, source, sourceDominant, context ); - mergeBuild_SourceDirectory( target, source, sourceDominant, context ); - mergeBuild_ScriptSourceDirectory( target, source, sourceDominant, context ); - mergeBuild_TestSourceDirectory( target, source, sourceDominant, context ); - mergeBuild_OutputDirectory( target, source, sourceDominant, context ); - mergeBuild_TestOutputDirectory( target, source, sourceDominant, context ); - mergeBuild_Extensions( target, source, sourceDominant, context ); - } - - protected void mergeBuild_SourceDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getSourceDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getSourceDirectory() == null ) - { - target.setSourceDirectory( src ); - target.setLocation( "sourceDirectory", source.getLocation( "sourceDirectory" ) ); - } - } - } - - protected void mergeBuild_ScriptSourceDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getScriptSourceDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getScriptSourceDirectory() == null ) - { - target.setScriptSourceDirectory( src ); - target.setLocation( "scriptSourceDirectory", source.getLocation( "scriptSourceDirectory" ) ); - } - } - } - - protected void mergeBuild_TestSourceDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getTestSourceDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getTestSourceDirectory() == null ) - { - target.setTestSourceDirectory( src ); - target.setLocation( "testSourceDirectory", source.getLocation( "testSourceDirectory" ) ); - } - } - } - - protected void mergeBuild_OutputDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getOutputDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getOutputDirectory() == null ) - { - target.setOutputDirectory( src ); - target.setLocation( "outputDirectory", source.getLocation( "outputDirectory" ) ); - } - } - } - - protected void mergeBuild_TestOutputDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getTestOutputDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getTestOutputDirectory() == null ) - { - target.setTestOutputDirectory( src ); - target.setLocation( "testOutputDirectory", source.getLocation( "testOutputDirectory" ) ); - } - } - } - - protected void mergeBuild_Extensions( Build target, Build source, boolean sourceDominant, - Map context ) - { - target.setExtensions( merge( target.getExtensions(), source.getExtensions(), - sourceDominant, getExtensionKey() ) ); - } - - protected void mergeExtension( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - mergeExtension_GroupId( target, source, sourceDominant, context ); - mergeExtension_ArtifactId( target, source, sourceDominant, context ); - mergeExtension_Version( target, source, sourceDominant, context ); - } - - protected void mergeExtension_GroupId( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeExtension_ArtifactId( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeExtension_Version( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeBuildBase( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - mergePluginConfiguration( target, source, sourceDominant, context ); - mergeBuildBase_DefaultGoal( target, source, sourceDominant, context ); - mergeBuildBase_FinalName( target, source, sourceDominant, context ); - mergeBuildBase_Directory( target, source, sourceDominant, context ); - mergeBuildBase_Resources( target, source, sourceDominant, context ); - mergeBuildBase_TestResources( target, source, sourceDominant, context ); - mergeBuildBase_Filters( target, source, sourceDominant, context ); - } - - protected void mergeBuildBase_DefaultGoal( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - String src = source.getDefaultGoal(); - if ( src != null ) - { - if ( sourceDominant || target.getDefaultGoal() == null ) - { - target.setDefaultGoal( src ); - target.setLocation( "defaultGoal", source.getLocation( "defaultGoal" ) ); - } - } - } - - protected void mergeBuildBase_Directory( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - String src = source.getDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getDirectory() == null ) - { - target.setDirectory( src ); - target.setLocation( "directory", source.getLocation( "directory" ) ); - } - } - } - - protected void mergeBuildBase_FinalName( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - String src = source.getFinalName(); - if ( src != null ) - { - if ( sourceDominant || target.getFinalName() == null ) - { - target.setFinalName( src ); - target.setLocation( "finalName", source.getLocation( "finalName" ) ); - } - } - } - - protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - target.setFilters( merge( target.getFilters(), source.getFilters(), sourceDominant, e -> e ) ); - } - - protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - target.setResources( merge( target.getResources(), source.getResources(), - sourceDominant, getResourceKey() ) ); - } - - protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - target.setTestResources( merge( target.getTestResources(), source.getTestResources(), - sourceDominant, getResourceKey() ) ); - } - - protected void mergePluginConfiguration( PluginConfiguration target, PluginConfiguration source, - boolean sourceDominant, Map context ) - { - mergePluginContainer( target, source, sourceDominant, context ); - mergePluginConfiguration_PluginManagement( target, source, sourceDominant, context ); - } - - protected void mergePluginConfiguration_PluginManagement( PluginConfiguration target, PluginConfiguration source, - boolean sourceDominant, Map context ) - { - PluginManagement src = source.getPluginManagement(); - if ( src != null ) - { - PluginManagement tgt = target.getPluginManagement(); - if ( tgt == null ) - { - tgt = new PluginManagement(); - target.setPluginManagement( tgt ); - } - mergePluginManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergePluginContainer( PluginContainer target, PluginContainer source, - boolean sourceDominant, Map context ) - { - mergePluginContainer_Plugins( target, source, sourceDominant, context ); - } - - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, - boolean sourceDominant, Map context ) - { - target.setPlugins( merge( target.getPlugins(), source.getPlugins(), - sourceDominant, getPluginKey() ) ); - } - - protected void mergePluginManagement( PluginManagement target, PluginManagement source, boolean sourceDominant, - Map context ) - { - mergePluginContainer( target, source, sourceDominant, context ); - } - - protected void mergePlugin( Plugin target, Plugin source, boolean sourceDominant, Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergePlugin_GroupId( target, source, sourceDominant, context ); - mergePlugin_ArtifactId( target, source, sourceDominant, context ); - mergePlugin_Version( target, source, sourceDominant, context ); - mergePlugin_Extensions( target, source, sourceDominant, context ); - mergePlugin_Dependencies( target, source, sourceDominant, context ); - mergePlugin_Executions( target, source, sourceDominant, context ); - } - - protected void mergePlugin_GroupId( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergePlugin_ArtifactId( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergePlugin_Version( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergePlugin_Extensions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getExtensions(); - if ( src != null ) - { - if ( sourceDominant || target.getExtensions() == null ) - { - target.setExtensions( src ); - target.setLocation( "extensions", source.getLocation( "extensions" ) ); - } - } - } - - protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - target.setDependencies( merge( target.getDependencies(), source.getDependencies(), - sourceDominant, getDependencyKey() ) ); - } - - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - target.setExecutions( merge( target.getExecutions(), source.getExecutions(), - sourceDominant, getPluginExecutionKey() ) ); - } - - protected void mergeConfigurationContainer( ConfigurationContainer target, ConfigurationContainer source, - boolean sourceDominant, Map context ) - { - mergeConfigurationContainer_Inherited( target, source, sourceDominant, context ); - mergeConfigurationContainer_Configuration( target, source, sourceDominant, context ); - } - - protected void mergeConfigurationContainer_Inherited( ConfigurationContainer target, ConfigurationContainer source, - boolean sourceDominant, Map context ) - { - String src = source.getInherited(); - if ( src != null ) - { - if ( sourceDominant || target.getInherited() == null ) - { - target.setInherited( src ); - target.setLocation( "inherited", source.getLocation( "inherited" ) ); - } - } - } - - protected void mergeConfigurationContainer_Configuration( ConfigurationContainer target, - ConfigurationContainer source, boolean sourceDominant, - Map context ) - { - Xpp3Dom src = (Xpp3Dom) source.getConfiguration(); - if ( src != null ) - { - Xpp3Dom tgt = (Xpp3Dom) target.getConfiguration(); - if ( sourceDominant || tgt == null ) - { - tgt = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( src ), tgt ); - } - else - { - tgt = Xpp3Dom.mergeXpp3Dom( tgt, src ); - } - target.setConfiguration( tgt ); - } - } - - protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergePluginExecution_Id( target, source, sourceDominant, context ); - mergePluginExecution_Phase( target, source, sourceDominant, context ); - mergePluginExecution_Goals( target, source, sourceDominant, context ); - } - - protected void mergePluginExecution_Id( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergePluginExecution_Phase( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - String src = source.getPhase(); - if ( src != null ) - { - if ( sourceDominant || target.getPhase() == null ) - { - target.setPhase( src ); - target.setLocation( "phase", source.getLocation( "phase" ) ); - } - } - } - - protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - target.setGoals( merge( target.getGoals(), source.getGoals(), sourceDominant, e -> e ) ); - } - - protected void mergeResource( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - mergeFileSet( target, source, sourceDominant, context ); - mergeResource_TargetPath( target, source, sourceDominant, context ); - mergeResource_Filtering( target, source, sourceDominant, context ); - mergeResource_MergeId( target, source, sourceDominant, context ); - } - - protected void mergeResource_TargetPath( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - String src = source.getTargetPath(); - if ( src != null ) - { - if ( sourceDominant || target.getTargetPath() == null ) - { - target.setTargetPath( src ); - target.setLocation( "targetPath", source.getLocation( "targetPath" ) ); - } - } - } - - protected void mergeResource_Filtering( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - String src = source.getFiltering(); - if ( src != null ) - { - if ( sourceDominant || target.getFiltering() == null ) - { - target.setFiltering( src ); - target.setLocation( "filtering", source.getLocation( "filtering" ) ); - } - } - } - - protected void mergeResource_MergeId( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - String src = source.getMergeId(); - if ( src != null ) - { - if ( sourceDominant || target.getMergeId() == null ) - { - target.setMergeId( src ); - } - } - } - - protected void mergeFileSet( FileSet target, FileSet source, boolean sourceDominant, Map context ) - { - mergePatternSet( target, source, sourceDominant, context ); - mergeFileSet_Directory( target, source, sourceDominant, context ); - } - - protected void mergeFileSet_Directory( FileSet target, FileSet source, boolean sourceDominant, - Map context ) - { - String src = source.getDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getDirectory() == null ) - { - target.setDirectory( src ); - target.setLocation( "directory", source.getLocation( "directory" ) ); - } - } - } - - protected void mergePatternSet( PatternSet target, PatternSet source, boolean sourceDominant, - Map context ) - { - mergePatternSet_Includes( target, source, sourceDominant, context ); - mergePatternSet_Excludes( target, source, sourceDominant, context ); - } - - protected void mergePatternSet_Includes( PatternSet target, PatternSet source, boolean sourceDominant, - Map context ) - { - target.setIncludes( merge( target.getIncludes(), source.getIncludes(), sourceDominant, e -> e ) ); - } - - protected void mergePatternSet_Excludes( PatternSet target, PatternSet source, boolean sourceDominant, - Map context ) - { - target.setExcludes( merge( target.getExcludes(), source.getExcludes(), sourceDominant, e -> e ) ); - } - - protected void mergeProfile( Profile target, Profile source, boolean sourceDominant, Map context ) - { - mergeModelBase( target, source, sourceDominant, context ); - // TODO - } - - protected void mergeActivation( Activation target, Activation source, boolean sourceDominant, - Map context ) - { - // TODO - } - - @Deprecated - protected Object getDependencyKey( Dependency dependency ) - { - return dependency; - } - - @Deprecated - protected Object getPluginKey( Plugin plugin ) - { - return plugin; - } - - @Deprecated - protected Object getPluginExecutionKey( PluginExecution pluginExecution ) - { - return pluginExecution; - } - - @Deprecated - protected Object getReportPluginKey( ReportPlugin reportPlugin ) - { - return reportPlugin; - } - - @Deprecated - protected Object getReportSetKey( ReportSet reportSet ) - { - return reportSet; - } - - @Deprecated - protected Object getLicenseKey( License license ) - { - return license; - } - - @Deprecated - protected Object getMailingListKey( MailingList mailingList ) - { - return mailingList; - } - - @Deprecated - protected Object getDeveloperKey( Developer developer ) - { - return developer; - } - - @Deprecated - protected Object getContributorKey( Contributor contributor ) - { - return contributor; - } - - @Deprecated - protected Object getProfileKey( Profile profile ) - { - return profile; - } - - @Deprecated - protected Object getRepositoryKey( Repository repository ) - { - return getRepositoryBaseKey( repository ); - } - - @Deprecated - protected Object getRepositoryBaseKey( RepositoryBase repositoryBase ) - { - return repositoryBase; - } - - @Deprecated - protected Object getNotifierKey( Notifier notifier ) - { - return notifier; - } - - @Deprecated - protected Object getResourceKey( Resource resource ) - { - return resource; - } - - @Deprecated - protected Object getExtensionKey( Extension extension ) - { - return extension; - } - - @Deprecated - protected Object getExclusionKey( Exclusion exclusion ) - { - return exclusion; - } - - protected KeyComputer getDependencyKey() - { - return d -> d; - } - - protected KeyComputer getPluginKey() - { - return p -> p; - } - - protected KeyComputer getPluginExecutionKey() - { - return e -> e; - } - - protected KeyComputer getReportPluginKey() - { - return p -> p; - } - - protected KeyComputer getReportSetKey() - { - return s -> s; - } - - protected KeyComputer getLicenseKey() - { - return l -> l; - } - - protected KeyComputer getMailingListKey() - { - return l -> l; - } - - protected KeyComputer getDeveloperKey() - { - return d -> d; - } - - protected KeyComputer getContributorKey() - { - return c -> c; - } - - protected KeyComputer getProfileKey() - { - return p -> p; - } - - protected KeyComputer getRepositoryKey() - { - return r -> r; - } - - protected KeyComputer getRepositoryBaseKey() - { - return r -> r; - } - - protected KeyComputer getNotifierKey() - { - return n -> n; - } - - protected KeyComputer getResourceKey() - { - return r -> r; - } - - protected KeyComputer getExtensionKey() - { - return e -> e; - } - - protected KeyComputer getExclusionKey() - { - return e -> e; - } - - /** - * Use to compute keys for data structures - * @param the data structure type - */ - @FunctionalInterface - public interface KeyComputer extends Function - { - } - - /** - * Merge two lists - */ - private static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) - { - return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); - } - - private static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) - { - if ( src.isEmpty() ) - { - return tgt; - } - - MergingList list; - if ( tgt instanceof MergingList ) - { - list = (MergingList) tgt; - } - else - { - list = new MergingList<>( computer, src.size() + tgt.size() ); - list.mergeAll( tgt, ( t, s ) -> s ); - } - - list.mergeAll( src, remapping ); - return list; - } - - /** - * Merging list - * @param - */ - private static class MergingList extends AbstractList implements java.io.Serializable - { - - private final KeyComputer keyComputer; - private Map map; - private List list; - - MergingList( KeyComputer keyComputer, int initialCapacity ) - { - this.map = new LinkedHashMap<>( initialCapacity ); - this.keyComputer = keyComputer; - } - - Object writeReplace() throws ObjectStreamException - { - return new ArrayList<>( this ); - } - - @Override - public Iterator iterator() - { - if ( map != null ) - { - return map.values().iterator(); - } - else - { - return list.iterator(); - } - } - - void mergeAll( Collection vs, BinaryOperator remapping ) - { - if ( map == null ) - { - map = list.stream().collect( Collectors.toMap( keyComputer, - Function.identity(), - null, - LinkedHashMap::new ) ); - - list = null; - } - - if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) - { - for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) - { - Object key = e.getKey(); - V v = e.getValue(); - map.merge( key, v, remapping ); - } - } - else - { - for ( V v : vs ) - { - Object key = keyComputer.apply( v ); - - map.merge( key, v, remapping ); - } - } - } - - @Override - public boolean contains( Object o ) - { - if ( map != null ) - { - return map.containsValue( o ); - } - else - { - return list.contains( o ); - } - } - - private List asList() - { - if ( list == null ) - { - list = new ArrayList<>( map.values() ); - map = null; - } - return list; - } - - @Override - public void add( int index, V element ) - { - asList().add( index, element ); - } - - @Override - public V remove( int index ) - { - return asList().remove( index ); - } - - @Override - public V get( int index ) - { - return asList().get( index ); - } - - @Override - public int size() - { - if ( map != null ) - { - return map.size(); - } - else - { - return list.size(); - } - } - } -} diff --git a/maven-model/src/main/mdo/common.vm b/maven-model/src/main/mdo/common.vm new file mode 100644 index 000000000000..3c3f29cf7a27 --- /dev/null +++ b/maven-model/src/main/mdo/common.vm @@ -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. +*# +# +## +## The following loop code is required in order to change the type of the +## pomFile attribute to a java.nio.file.Path. Modello does not support this +## type and loading a model with such a type would fail the modello validation. +## +#foreach ( $field in $model.getClass("Model", $version).allFields ) + #if ( $field.name == "pomFile" ) + #set ( $dummy = $field.setType("java.nio.file.Path") ) + #end +#end +#set ( $locationTracking = true ) +# \ No newline at end of file diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm new file mode 100644 index 000000000000..e81c3baab302 --- /dev/null +++ b/maven-model/src/main/mdo/merger.vm @@ -0,0 +1,380 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Merger" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * Merges the specified source object into the given target object. + * + * @param target The target object whose existing contents should be merged with the source, must not be + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @param sourceDominant A flag indicating whether either the target object or the source object provides the + * dominant data. + * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific + * information along, may be null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( !src.isEmpty() ) + { + Properties tgt = target.get${capField}(); + if ( tgt.isEmpty() ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm new file mode 100644 index 000000000000..b6e33401b424 --- /dev/null +++ b/maven-model/src/main/mdo/model-v3.vm @@ -0,0 +1,312 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV3}" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.allFields ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.AbstractList" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) ) + #set ( $dummy = $imports.add( "java.util.stream.Stream" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.codehaus.plexus.util.xml.Xpp3Dom" ) ) + #set ( $dummy = $types.put( $field, "Object" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + implements Serializable, Cloneable + #else + extends BaseObject + #end +{ + + public ${class.name}() + { + this( ${packageModelV4}.${class.name}.newInstance() ); + } + + public ${class.name}( ${packageModelV4}.${class.name} delegate ) + { + this( delegate, null ); + } + + public ${class.name}( ${packageModelV4}.${class.name} delegate, BaseObject parent ) + { + super( delegate, parent ); + } + + public ${class.name} clone() + { + return new ${class.name}( getDelegate() ); + } + + #if ( $class.superClass ) + @Override + #end + public ${packageModelV4}.${class.name} getDelegate() + { + return ( ${packageModelV4}.${class.name} ) super.getDelegate(); + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return Objects.equals( this.delegate, that.delegate ); + } + + @Override + public int hashCode() + { + return getDelegate().hashCode(); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return getDelegate().getModelEncoding(); + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( + () -> getDelegate().get${cap}(), l -> update( getDelegate().with${cap}( l ) ), + d -> new ${field.to}( d, this ), ${field.to}::getDelegate ); + #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + return new WrapperProperties( () -> getDelegate().get${cap}(), this::set${cap} ); + #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList( () -> getDelegate().get${cap}(), this::set${cap}, s -> s, s -> s ); + #elseif ( $field.to ) + return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}(), this ) : null; + #elseif ( $field.type == "DOM" ) + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}(), this::replace ) : null; + #else + return getDelegate().${pfx}${cap}(); + #end + } + + public void set${cap}( ${type} ${field.name} ) + { + #if ( $field.type == "DOM" ) + if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) ) + { + update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) ); + ( ( Xpp3Dom ) ${field.name} ).setChildrenTracking( this::replace ); + } + #else + if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + update( getDelegate().with${cap}( + ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ) ); + ${field.name}.forEach( e -> e.childrenTracking = this::replace ); + #elseif ( $field.to && $field.to != "String" ) + update( getDelegate().with${cap}( ${field.name}.getDelegate() ) ); + ${field.name}.childrenTracking = this::replace; + #else + update( getDelegate().with${cap}( ${field.name} ) ); + #end + } + #end + } + + #if ( $field.type == "java.util.List" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( ${field.to} ${v} ) + { + #if ( $field.to == "String" ) + update( getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) + .collect( Collectors.toList() ) ) ); + #else + update( getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) + .collect( Collectors.toList() ) ) ); + ${v}.childrenTracking = this::replace; + #end + } + + public void remove${scap}( ${field.to} ${v} ) + { + #if ( $field.to == "String" ) + update( getDelegate().with${cap}( + getDelegate().get${cap}().stream() + .filter( e -> !Objects.equals( e, ${v} ) ) + .collect( Collectors.toList() ) ) ); + #else + update( getDelegate().with${cap}( + getDelegate().get${cap}().stream() + .filter( e -> !Objects.equals( e, ${v} ) ) + .collect( Collectors.toList() ) ) ); + ${v}.childrenTracking = null; + #end + } + + #end + #end + public InputLocation getLocation( Object key ) + { + ${packageModelV4}.InputLocation loc = getDelegate().getLocation( key ); + return loc != null ? new InputLocation( loc ) : null; + } + + public void setLocation( Object key, InputLocation location ) + { + update( ${packageModelV4}.${class.name}.newBuilder( getDelegate(), true ) + .location( key, location.toApiLocation() ).build() ); + } + + protected boolean replace( Object oldDelegate, Object newDelegate ) + { + if ( super.replace( oldDelegate, newDelegate ) ) + { + return true; + } + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.to && $field.multiplicity != "*" ) + if ( oldDelegate == getDelegate().get${cap}() ) + { + update( getDelegate().with${cap}( ( ${packageModelV4}.${field.to} ) newDelegate ) ); + return true; + } + #elseif ( $field.type == "java.util.List" && $field.to != "String" ) + if ( getDelegate().get${cap}().contains( oldDelegate ) ) + { + List<${packageModelV4}.${field.to}> list = new ArrayList<>( getDelegate().get${cap}() ); + list.replaceAll( d -> d == oldDelegate ? ( ${packageModelV4}.${field.to} ) newDelegate : d ); + update( getDelegate().with${cap}( list ) ); + return true; + } + #elseif ( $field.type == "DOM" ) + if ( getDelegate().get${cap}() == oldDelegate ) + { + update( getDelegate().with${cap}( ( org.apache.maven.api.xml.Dom ) newDelegate ) ); + } + #end + #end + return false; + } + + public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + { + return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; + } + + public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List<${packageModelV4}.${class.name}> list ) + { + return list != null ? new WrapperList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm new file mode 100644 index 000000000000..683d0a21e4a1 --- /dev/null +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -0,0 +1,532 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3ReaderEx" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, 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.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +import ${packageModelV4}.InputSource; +import ${packageModelV4}.InputLocation; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( ( s, f ) -> s ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + parser.setInput( reader ); + return read( parser, strict, source ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict, source ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict, source ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#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.allFields ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + ${classLcapName}.location( "", new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + ${classLcapName}.location( name, new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, strict, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = unalias( parser.getName() ); + if ( !parsed.add( childName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); + } + int line = parser.getLineNumber(); + int column = parser.getColumnNumber(); + Map locations = null; + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + locations = new HashMap<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + locations.put( Integer.valueOf( locations.size() ), new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + locations = new HashMap<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + locations.put( key, new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict, source ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict, source ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + ${classLcapName}.location( childName, new InputLocation( line, column, source, locations ) ); + } + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String unalias( String tagName ) + { + switch ( tagName ) + { +#set( $aliases = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.allFields ) + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) + #end + #end +#end +#foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + return "${entry.value}"; +#end + default: + return tagName; + } + } + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + +#foreach ( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "boolean" || $field.type == "Boolean" ) + #set ( $hasBooleanField = true ) + #elseif ( $field.type == "int" || $field.type == "Integer" ) + #set ( $hasIntegerField = true ) + #end + #end +#end +#if ( $hasBooleanField ) + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, boolean defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + return defaultValue; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + +#end +#if ( $hasIntegerField ) + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + +#end + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm new file mode 100644 index 000000000000..caa2f1059499 --- /dev/null +++ b/maven-model/src/main/mdo/reader.vm @@ -0,0 +1,551 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Reader" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, 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.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( ( s, f ) -> s ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#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.allFields ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = unalias( parser.getName() ); + if ( !parsed.add( childName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); + } + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String unalias( String tagName ) + { + switch ( tagName ) + { +#set( $aliases = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.allFields ) + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) + #end + #end +#end +#foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + return "${entry.value}"; +#end + default: + return tagName; + } + } + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + +#foreach ( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "boolean" || $field.type == "Boolean" ) + #set ( $hasBooleanField = true ) + #elseif ( $field.type == "int" || $field.type == "Integer" ) + #set ( $hasIntegerField = true ) + #end + #end +#end +#if ( $hasBooleanField ) + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, boolean defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + return defaultValue; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + +#end +#if ( $hasIntegerField ) + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + +#end + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm new file mode 100644 index 000000000000..8c7380b2be57 --- /dev/null +++ b/maven-model/src/main/mdo/transformer.vm @@ -0,0 +1,205 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Transformer" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.xml.Xpp3Dom; + +@Generated +public class ${className} +{ + + private final Function transformer; + + public ${className}( Function transformer ) + { + this.transformer = transformer; + } + + /** + * Transforms the given model + */ + public ${root.name} visit( ${root.name} target ) + { + Objects.requireNonNull( target, "target cannot be null" ); + return transform${root.name}( target ); + } + + /** + * The transformation function. + */ + protected String transform( String value ) + { + return transformer.apply( value ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + protected ${class.name} transform${class.name}( ${class.name} target ) + { + if ( target == null ) + { + return null; + } + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + #foreach ( $field in $allFields ) + transform${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target ); + #end + return builder.build(); + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void transform${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target ) + { + #if ( $field.type == "String" ) + String newVal = transform( target.get${capField}() ); + builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( transform( target.get${capField}(), this::transform ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties props = target.get${capField}(); + Properties newProps = null; + for ( Map.Entry entry : props.entrySet() ) + { + if ( entry.getKey() instanceof String && entry.getValue() instanceof String ) + { + String newVal = transform( ( String ) entry.getValue() ); + if ( newVal != null && newVal != entry.getValue() ) + { + if ( newProps == null ) + { + newProps = new Properties(); + newProps.putAll( props ); + builder.${field.name}( newProps ); + } + newProps.put( ( String ) entry.getKey(), newVal ); + } + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} newVal = transform${field.to}( target.get${capField}() ); + builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( transform( target.get${capField}(), this::transform${field.to} ) ); + #elseif ( $field.type == "DOM" ) + Dom newVal = transform( target.get${capField}() ); + builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); + #elseif ( $field.type == "boolean" || $field.type == "int" || $field.type == "java.nio.file.Path" ) + // nothing to do, the transformer only handles strings + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + protected List transform( List list, Function transformer ) + { + List newList = null; + for ( int i = 0; i < list.size(); i++ ) + { + T newVal = transformer.apply( list.get( i ) ); + if ( newVal != list.get( i ) ) + { + if ( newList == null ) + { + newList = new ArrayList<>( list ); + } + newList.set( i, newVal ); + } + } + return newList; + } + + protected Dom transform( Dom node ) + { + if ( node != null ) + { + Xpp3Dom xpp = new Xpp3Dom( node ); + transform( xpp ); + return xpp.getDom(); + } + return node; + } + + protected void transform( Xpp3Dom dom ) + { + if ( dom != null ) + { + String org, val; + // Content + org = dom.getValue(); + val = transform( org ); + if ( org != val ) + { + dom.setValue( val ); + } + // Attributes + for ( String attr : dom.getAttributeNames() ) + { + org = dom.getAttribute( attr ); + val = transform( org ); + if ( org != val ) + { + dom.setAttribute( attr, val ); + } + } + // Children + for ( int i = 0, l = dom.getChildCount(); i < l; i++ ) + { + transform( dom.getChild( i ) ); + } + } + } +} diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm new file mode 100644 index 000000000000..de458ed3c366 --- /dev/null +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -0,0 +1,393 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3WriterEx" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import ${packageModelV4}.InputLocation; +import ${packageModelV4}.InputLocationTracker; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputLocation" ) +import ${packageModelV4}.${class.name}; + #end +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + /** + * Field stringFormatter. + */ + protected InputLocation.StringFormatter stringFormatter; + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method setStringFormatter. + * + * @param stringFormatter + */ + public void setStringFormatter( InputLocation.StringFormatter stringFormatter ) + { + this.stringFormatter = stringFormatter; + } //-- void setStringFormatter( InputLocation.StringFormatter ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#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 ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName} ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName} ); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer, ${classLcapName} ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer, ${classLcapName} ); + #end + #elseif ( $field.type == "int" ) + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer, ${classLcapName} ); + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName}, + t -> writeTag( "$singularField", null, t, serializer, null ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName} ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName}, + t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + writeLocationTracking( ${classLcapName}, "", serializer ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, InputLocationTracker locationTracker, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, locationTracker, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, InputLocationTracker locationTracker, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + int index = 0; + InputLocation location = locationTracker != null ? locationTracker.getLocation( tagName ) : null; + for ( T t : list ) + { + writer.write( t ); + writeLocationTracking( location, Integer.valueOf( index++ ), serializer ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + writeLocationTracking( locationTracker, tagName, serializer ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer, InputLocationTracker locationTracker ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + InputLocation location = locationTracker != null ? locationTracker.getLocation( tagName ) : null; + for ( Map.Entry entry : props.entrySet() ) + { + String key = entry.getKey().toString(); + writeTag( key, null, entry.getValue().toString(), serializer, null ); + writeLocationTracking( location, key, serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + writeLocationTracking( locationTracker, tagName, serializer ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer, InputLocationTracker locationTracker ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + writeLocationTracking( locationTracker, tagName, serializer ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + + /** + * Method writeLocationTracking. + * + * @param locationTracker + * @param serializer + * @param key + * @throws java.io.IOException + */ + protected void writeLocationTracking( InputLocationTracker locationTracker, Object key, XmlSerializer serializer ) + throws java.io.IOException + { + InputLocation location = ( locationTracker == null ) ? null : locationTracker.getLocation( key ); + if ( location != null ) + { + serializer.comment( toString( location ) ); + } + } //-- void writeLocationTracking( InputLocationTracker, Object, XmlSerializer ) + + /** + * Method toString. + * + * @param location + * @return String + */ + protected String toString( InputLocation location ) + { + if ( stringFormatter != null ) + { + return stringFormatter.toString( location ); + } + return ' ' + location.getSource().toString() + ':' + location.getLineNumber() + ' '; + } //-- String toString( InputLocation ) +} diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm new file mode 100644 index 000000000000..e2740f45a4d3 --- /dev/null +++ b/maven-model/src/main/mdo/writer.vm @@ -0,0 +1,331 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Writer" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#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 ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java b/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java similarity index 84% rename from maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java rename to maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java index f1aad049f848..02b3a32fa2b3 100644 --- a/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java +++ b/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java @@ -1,9 +1,5 @@ package org.apache.maven.model.merge; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.is; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -23,88 +19,71 @@ * under the License. */ -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; import java.util.Arrays; -import org.apache.maven.model.Build; -import org.apache.maven.model.Contributor; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Developer; -import org.apache.maven.model.License; -import org.apache.maven.model.MailingList; -import org.apache.maven.model.Model; -import org.apache.maven.model.PatternSet; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Contributor; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenMerger; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.is; + /** - * ModelMerger is based on same instances, subclasses should override KeyComputer per type + * MavenMerger is based on same instances, subclasses should override KeyComputer per type * * @author Robert Scholte * */ -public class ModelMergerTest +public class MavenMergerTest { - private ModelMerger modelMerger = new ModelMerger(); + private MavenMerger mavenMerger = new MavenMerger(); @Test public void mergeArtifactId() { - Model target = new Model(); - target.setArtifactId( "TARGET" ); + Model target = Model.newBuilder().artifactId( "TARGET" ).build(); - Model source = new Model(); - source.setArtifactId( "SOURCE" ); + Model source = Model.newBuilder().artifactId( "SOURCE" ).build(); - modelMerger.merge( target, source, true, null ); - assertThat( target.getArtifactId(), is( "SOURCE" ) ); + Model merged = mavenMerger.merge( target, source, true, null ); + assertThat( merged.getArtifactId(), is( "SOURCE" ) ); - target.setArtifactId( "TARGET" );; - modelMerger.merge( target, source, false, null ); - assertThat( target.getArtifactId(), is( "TARGET" ) ); + merged = mavenMerger.merge( target, source, false, null ); + assertThat( merged.getArtifactId(), is( "TARGET" ) ); } @Test public void mergeSameContributors() { - Contributor contributor = new Contributor(); - contributor.setEmail( "contributor@maven.apache.org" ); + Contributor contributor = Contributor.newBuilder().email( "contributor@maven.apache.org" ).build(); - Model target = new Model(); - target.setContributors( Arrays.asList( contributor ) ); + Model target = Model.newBuilder().contributors( Arrays.asList( contributor ) ).build(); - Model source = new Model(); - source.setContributors( Arrays.asList( contributor ) ); + Model source = Model.newBuilder().contributors( Arrays.asList( contributor ) ).build(); - modelMerger.merge( target, source, true, null ); + Model merged = mavenMerger.merge( target, source, true, null ); - assertThat( target.getContributors(), contains( contributor ) ); + assertThat( merged.getContributors(), contains( contributor ) ); } @Test public void mergeSameDependencies() { - Dependency dependency = new Dependency(); - dependency.setGroupId( "groupId" ); - dependency.setArtifactId( "artifactId" ); - dependency.setType( "type" ); + Dependency dependency = Dependency.newBuilder().groupId( "groupId" ).artifactId( "artifactId" ).type( "type" ).build(); - Model target = new Model(); - target.setDependencies( Arrays.asList( dependency ) ); + Model target = Model.newBuilder().dependencies( Arrays.asList( dependency ) ).build(); - Model source = new Model(); - source.setDependencies( Arrays.asList( dependency ) ); + Model source = Model.newBuilder().dependencies( Arrays.asList( dependency ) ).build(); - modelMerger.merge( target, source, true, null ); + Model merged = mavenMerger.merge( target, source, true, null ); - assertThat( target.getDependencies(), contains( dependency ) ); + assertThat( merged.getDependencies(), contains( dependency ) ); } + /* @Test public void mergeDescription() { @@ -441,10 +420,11 @@ public void testMergedModelSerialization() throws Exception { source.setLicenses(new ArrayList()); source.getLicenses().add(lic2); - new ModelMerger().mergeModel(target, source, false, null); + new MavenMerger().mergeModel(target, source, false, null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(target); } + */ } diff --git a/maven-plugin-api/pom.xml b/maven-plugin-api/pom.xml index be4b99399f7d..828eaf49c18d 100644 --- a/maven-plugin-api/pom.xml +++ b/maven-plugin-api/pom.xml @@ -61,13 +61,23 @@ under the License. org.codehaus.modello modello-maven-plugin + 2.0.0 + + + modello + none + modello-site-doc pre-site @@ -82,6 +92,36 @@ under the License. + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + + velocity + generate-sources + + velocity + + + 1.0.0 + + src/main/mdo/lifecycle.mdo + + + + + + + + packageModelV3=org.apache.maven.plugin.lifecycle + packageModelV4=org.apache.maven.plugin.lifecycle + packageToolV4=org.apache.maven.plugin.lifecycle.io.xpp3 + + + + + diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java index 9d946b595715..80829332a972 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java @@ -139,6 +139,8 @@ public class MojoDescriptor */ private boolean threadSafe = false; + private boolean v4Api = false; + /** * Default constructor. */ @@ -455,7 +457,7 @@ public void setMojoConfiguration( PlexusConfiguration mojoConfiguration ) /** {@inheritDoc} */ public String getRole() { - return Mojo.ROLE; + return isV4Api() ? "org.apache.maven.api.plugin.Mojo" : Mojo.ROLE; } /** {@inheritDoc} */ @@ -656,6 +658,16 @@ public boolean isForking() || ( getExecutePhase() != null && getExecutePhase().length() > 0 ); } + public boolean isV4Api() + { + return v4Api; + } + + public void setV4Api( boolean v4Api ) + { + this.v4Api = v4Api; + } + /** * Creates a shallow copy of this mojo descriptor. */ diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java index 5747d16e9a83..a60985f1a4e2 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java @@ -24,12 +24,12 @@ import java.util.ArrayList; import java.util.List; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; +import org.apache.maven.internal.xml.Xpp3DomBuilder; import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.component.repository.ComponentRequirement; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfigurationException; -import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; -import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** @@ -309,6 +309,13 @@ public MojoDescriptor buildComponentDescriptor( PlexusConfiguration c, PluginDes mojo.setThreadSafe( Boolean.parseBoolean( threadSafe ) ); } + String v4Api = c.getChild( "v4Api" ).getValue(); + + if ( v4Api != null ) + { + mojo.setV4Api( Boolean.parseBoolean( v4Api ) ); + } + // ---------------------------------------------------------------------- // Configuration // ---------------------------------------------------------------------- @@ -401,7 +408,7 @@ public PlexusConfiguration buildConfiguration( Reader configuration ) { try { - return new XmlPlexusConfiguration( Xpp3DomBuilder.build( configuration ) ); + return XmlPlexusConfiguration.toPlexusConfiguration( Xpp3DomBuilder.build( configuration ) ); } catch ( IOException | XmlPullParserException e ) { diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java new file mode 100644 index 000000000000..4479e411361d --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.plugin.lifecycle; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/maven-plugin-api/src/main/mdo/common.vm b/maven-plugin-api/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/maven-plugin-api/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/maven-plugin-api/src/main/mdo/merger.vm b/maven-plugin-api/src/main/mdo/merger.vm new file mode 100644 index 000000000000..e81c3baab302 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/merger.vm @@ -0,0 +1,380 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Merger" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * Merges the specified source object into the given target object. + * + * @param target The target object whose existing contents should be merged with the source, must not be + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @param sourceDominant A flag indicating whether either the target object or the source object provides the + * dominant data. + * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific + * information along, may be null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( !src.isEmpty() ) + { + Properties tgt = target.get${capField}(); + if ( tgt.isEmpty() ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm new file mode 100644 index 000000000000..e995fa6e9478 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -0,0 +1,516 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Generated @ThreadSafe @Immutable +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else + implements Serializable + #end +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ + final ${type} $field.name; + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + InputLocation location, + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} + #end + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + location, + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else + this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end + #end + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull + public ${class.name} with${cap}( $type $field.name ) + { + return with().${field.name}( $field.name ).build(); + } + #end + + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull + public static Builder newBuilder() + { + return newBuilder( true ); + } + + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + @Nonnull + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull + public Builder ${field.name}( ${type} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + #if ( $locationTracking ) + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + #end + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), + #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + #if ( $locationTracking ) + locations, + location != null ? location : ( base != null ? base.location : null ), + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-plugin-api/src/main/mdo/reader.vm b/maven-plugin-api/src/main/mdo/reader.vm new file mode 100644 index 000000000000..a575b6534b94 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/reader.vm @@ -0,0 +1,899 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Reader" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, 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.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( ( s, f ) -> s ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + return getIntegerValue( s, attribute, parser, strict, 0 ); + } //-- int getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean, int ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#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 + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + List<$field.to> ${field.name} = new ArrayList<>(); + #end + #end + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = checkDuplicate( parser.getName(), parser, parsed ); + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #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}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}( ${field.name} ); + #end + #end + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String checkDuplicate( String tagName, XmlPullParser parser, Set parsed ) + throws XmlPullParserException + { +#set( $aliases = { } ) +#set( $flats = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular($fieldTagName) ) + #set ( $dummy = $flats.put( $fieldTagName, "" ) ) + #end + #end +#end +#if ( ! ${aliases.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + tagName = "${entry.value}"; + #end + } +#end +#if ( ! ${flats.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $flats.entrySet() ) + case "${entry.key}": + #end + break; + default: + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + } +#end + return tagName; + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-plugin-api/src/main/mdo/writer.vm b/maven-plugin-api/src/main/mdo/writer.vm new file mode 100644 index 000000000000..e2740f45a4d3 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/writer.vm @@ -0,0 +1,331 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Writer" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#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 ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-resolver-provider/pom.xml b/maven-resolver-provider/pom.xml index c3ece6a26c62..2b0ce48de042 100644 --- a/maven-resolver-provider/pom.xml +++ b/maven-resolver-provider/pom.xml @@ -151,6 +151,15 @@ under the License. org.eclipse.sisu sisu-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java index 17fbb1001307..b387e9967182 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java @@ -57,6 +57,7 @@ public static RemoteRepository toRemoteRepository( Repository repository ) return builder.build(); } + public static RepositoryPolicy toRepositoryPolicy( org.apache.maven.model.RepositoryPolicy policy ) { boolean enabled = true; diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java index f23bfe4ef8b6..e2bb7a5bc2e8 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java @@ -25,10 +25,11 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.building.ArtifactModelSource; import org.apache.maven.model.building.ModelSource; import org.apache.maven.model.resolution.InvalidRepositoryException; @@ -133,7 +134,8 @@ public void addRepository( final Repository repository, boolean replace ) } List newRepositories = - Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( repository ) ); + Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( + new org.apache.maven.model.Repository( repository ) ) ); this.repositories = remoteRepositoryManager.aggregateRepositories( session, repositories, newRepositories, true ); @@ -179,7 +181,7 @@ public ModelSource resolveModel( String groupId, String artifactId, String versi } @Override - public ModelSource resolveModel( final Parent parent ) + public ModelSource resolveModel( final Parent parent, final AtomicReference modified ) throws UnresolvableModelException { try @@ -214,9 +216,13 @@ public ModelSource resolveModel( final Parent parent ) } - parent.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !parent.getVersion().equals( newVersion ) ) + { + modified.set( parent.withVersion( newVersion ) ); + } - return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); + return resolveModel( parent.getGroupId(), parent.getArtifactId(), newVersion ); } catch ( final VersionRangeResolutionException e ) { @@ -227,7 +233,7 @@ public ModelSource resolveModel( final Parent parent ) } @Override - public ModelSource resolveModel( final Dependency dependency ) + public ModelSource resolveModel( final Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { try @@ -262,9 +268,13 @@ public ModelSource resolveModel( final Dependency dependency ) } - dependency.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !dependency.getVersion().equals( newVersion ) ) + { + modified.set( dependency.withVersion( newVersion ) ); + } - return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), newVersion ); } catch ( VersionRangeResolutionException e ) { @@ -273,4 +283,41 @@ public ModelSource resolveModel( final Dependency dependency ) } } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException + { + AtomicReference resolvedParent = new AtomicReference<>(); + ModelSource result = resolveModel( parent.getDelegate(), resolvedParent ); + if ( resolvedParent.get() != null ) + { + parent.setVersion( resolvedParent.get().getVersion() ); + } + return result; + } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException + { + AtomicReference resolvedDependency = new AtomicReference<>(); + ModelSource result = resolveModel( dependency.getDelegate(), resolvedDependency ); + if ( resolvedDependency.get() != null ) + { + dependency.setVersion( resolvedDependency.get().getVersion() ); + } + return result; + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException + { + addRepository( repository.getDelegate() ); + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository, boolean replace ) + throws InvalidRepositoryException + { + addRepository( repository.getDelegate(), replace ); + } } diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java index 629a23f3bea1..49b3aabf8b1e 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java @@ -39,6 +39,9 @@ interface PluginInfo /** * Returns {@link PluginInfo} corresponding for passed in {@link Artifact}, or {@code null}. + * + * @param artifact the artifact + * @return the plugin info */ PluginInfo getPluginInfo( Artifact artifact ); } diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java index a0a21e9a6002..d12454f94bab 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java @@ -152,4 +152,5 @@ public String getMessage() { return message; } + } diff --git a/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java b/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java index 1a4d444de4c0..350e0ab2fa5d 100644 --- a/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java +++ b/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java @@ -21,9 +21,10 @@ import java.net.MalformedURLException; import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Parent; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @@ -57,14 +58,14 @@ public DefaultModelResolverTest() @Test public void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "0" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "0" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertTrue( e.getMessage().startsWith( "Could not find artifact ut.simple:artifact:pom:0 in repo" ) ); @@ -73,14 +74,14 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() thro @Test public void testResolveParentThrowsUnresolvableModelExceptionWhenNoMatchingVersionFound() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "[2.0,2.1)" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[2.0,2.1)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertEquals( "No versions matched the requested parent version range '[2.0,2.1)'", @@ -90,14 +91,14 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNoMatchingVersi @Test public void testResolveParentThrowsUnresolvableModelExceptionWhenUsingRangesWithoutUpperBound() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "[1.0,)" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[1.0,)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested parent version range '[1.0,)' does not specify an upper bound", e.getMessage() ); @@ -106,38 +107,40 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenUsingRangesWith @Test public void testResolveParentSuccessfullyResolvesExistingParentWithoutRange() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "1.0" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "1.0" ).build(); - assertNotNull( this.newModelResolver().resolveModel( parent ) ); + assertNotNull( this.newModelResolver().resolveModel( parent, new AtomicReference<>() ) ); assertEquals( "1.0", parent.getVersion() ); } @Test public void testResolveParentSuccessfullyResolvesExistingParentUsingHighestVersion() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "(,2.0)" ); - - assertNotNull( this.newModelResolver().resolveModel( parent ) ); - assertEquals( "1.0", parent.getVersion() ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "(,2.0)" ).build(); + + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( parent, modified ) ); + assertNotNull( modified.get() ); + assertEquals( "1.0", modified.get().getVersion() ); } @Test public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "0" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "0" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertTrue( e.getMessage().startsWith( "Could not find artifact ut.simple:artifact:pom:0 in repo" ) ); @@ -146,14 +149,14 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() @Test public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNoMatchingVersionFound() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "[2.0,2.1)" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[2.0,2.1)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "No versions matched the requested dependency version range '[2.0,2.1)'", e.getMessage() ); @@ -162,14 +165,14 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNoMatchingV @Test public void testResolveDependencyThrowsUnresolvableModelExceptionWhenUsingRangesWithoutUpperBound() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "[1.0,)" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[1.0,)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested dependency version range '[1.0,)' does not specify an upper bound", e.getMessage() ); @@ -178,25 +181,27 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenUsingRanges @Test public void testResolveDependencySuccessfullyResolvesExistingDependencyWithoutRange() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "1.0" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "1.0" ).build(); - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); + assertNotNull( this.newModelResolver().resolveModel( dependency, new AtomicReference<>() ) ); assertEquals( "1.0", dependency.getVersion() ); } @Test public void testResolveDependencySuccessfullyResolvesExistingDependencyUsingHighestVersion() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "(,2.0)" ); - - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); - assertEquals( "1.0", dependency.getVersion() ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "(,2.0)" ).build(); + + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( dependency, modified ) ); + assertNotNull( modified.get() ); + assertEquals( "1.0", modified.get().getVersion() ); } private ModelResolver newModelResolver() throws ComponentLookupException, MalformedURLException diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java index 0d1a1b601e7e..183d4f77b878 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java @@ -33,8 +33,8 @@ import org.apache.maven.building.FileSource; import org.apache.maven.building.Source; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.TrackableBase; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.api.settings.TrackableBase; import org.apache.maven.settings.io.SettingsParseException; import org.apache.maven.settings.io.SettingsReader; import org.apache.maven.settings.io.SettingsWriter; @@ -106,7 +106,7 @@ public SettingsBuildingResult build( SettingsBuildingRequest request ) getSettingsSource( request.getUserSettingsFile(), request.getUserSettingsSource() ); Settings userSettings = readSettings( userSettingsSource, request, problems ); - settingsMerger.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL ); + userSettings = settingsMerger.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL ); problems.setSource( "" ); @@ -119,7 +119,7 @@ public SettingsBuildingResult build( SettingsBuildingRequest request ) File file = new File( localRepository ); if ( !file.isAbsolute() && file.getPath().startsWith( File.separator ) ) { - userSettings.setLocalRepository( file.getAbsolutePath() ); + userSettings = userSettings.withLocalRepository( file.getAbsolutePath() ); } } @@ -165,7 +165,7 @@ private Settings readSettings( Source settingsSource, SettingsBuildingRequest re { if ( settingsSource == null ) { - return new Settings(); + return Settings.newInstance(); } problems.setSource( settingsSource.getLocation() ); @@ -194,13 +194,13 @@ private Settings readSettings( Source settingsSource, SettingsBuildingRequest re { problems.add( SettingsProblem.Severity.FATAL, "Non-parseable settings " + settingsSource.getLocation() + ": " + e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e ); - return new Settings(); + return Settings.newInstance(); } catch ( IOException e ) { problems.add( SettingsProblem.Severity.FATAL, "Non-readable settings " + settingsSource.getLocation() + ": " + e.getMessage(), -1, -1, e ); - return new Settings(); + return Settings.newInstance(); } settingsValidator.validate( settings, problems ); diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java index 48456e5d6527..4dc59d7e275f 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; /** * Collects the output of the settings builder. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java index 43b2359fac08..d2c2c11ebcb2 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java @@ -21,7 +21,7 @@ import java.util.List; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; /** * Collects the output of the settings builder. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java index 7d6c8b9b6623..bd0e21b80f7b 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java @@ -26,8 +26,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; import org.apache.maven.settings.building.DefaultSettingsProblem; import org.apache.maven.settings.building.SettingsProblem; import org.apache.maven.settings.building.SettingsProblem.Severity; @@ -61,13 +61,9 @@ public SettingsDecryptionResult decrypt( SettingsDecryptionRequest request ) for ( Server server : request.getServers() ) { - server = server.clone(); - - servers.add( server ); - try { - server.setPassword( decrypt( server.getPassword() ) ); + server = server.withPassword( decrypt( server.getPassword() ) ); } catch ( SecDispatcherException e ) { @@ -77,32 +73,32 @@ public SettingsDecryptionResult decrypt( SettingsDecryptionRequest request ) try { - server.setPassphrase( decrypt( server.getPassphrase() ) ); + server = server.withPassphrase( decrypt( server.getPassphrase() ) ); } catch ( SecDispatcherException e ) { problems.add( new DefaultSettingsProblem( "Failed to decrypt passphrase for server " + server.getId() + ": " + e.getMessage(), Severity.ERROR, "server: " + server.getId(), -1, -1, e ) ); } + + servers.add( server ); } List proxies = new ArrayList<>(); for ( Proxy proxy : request.getProxies() ) { - proxy = proxy.clone(); - - proxies.add( proxy ); - try { - proxy.setPassword( decrypt( proxy.getPassword() ) ); + proxy = proxy.withPassword( decrypt( proxy.getPassword() ) ); } catch ( SecDispatcherException e ) { problems.add( new DefaultSettingsProblem( "Failed to decrypt password for proxy " + proxy.getId() + ": " + e.getMessage(), Severity.ERROR, "proxy: " + proxy.getId(), -1, -1, e ) ); } + + proxies.add( proxy ); } return new DefaultSettingsDecryptionResult( servers, proxies, problems ); diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java index 9cb49ac40da2..4281a6c8c8e4 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java @@ -23,9 +23,9 @@ import java.util.Arrays; import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; +import org.apache.maven.api.settings.Settings; /** * Collects parameters that control the decryption of settings. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java index ccdad196db25..d52f126960cc 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; import org.apache.maven.settings.building.SettingsProblem; /** diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java index b344a99ed928..33c61a6aef87 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; /** * Collects parameters that control the decryption of settings. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java index 5b7b1f4b5a31..a8d88b65b980 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; import org.apache.maven.settings.building.SettingsProblem; /** diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java index 4ce48dd0acdf..7662abc68099 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java @@ -29,8 +29,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.v4.SettingsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java index 54f626a22e60..74bbfe4bbc5b 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java @@ -30,8 +30,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.v4.SettingsXpp3Writer; import org.codehaus.plexus.util.WriterFactory; /** diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java index 7817df6577bc..802d857706c2 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java @@ -25,7 +25,7 @@ import java.io.Reader; import java.util.Map; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; /** * Handles deserialization of settings from some kind of textual format like XML. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java index 54bfcf0ce1ad..d6444bc28fcc 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java @@ -25,7 +25,7 @@ import java.io.Writer; import java.util.Map; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; /** * Handles serialization of settings into some kind of textual format like XML. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java index cb5f6c166f1f..241310f74633 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java @@ -20,12 +20,16 @@ */ import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; -import org.apache.maven.settings.IdentifiableBase; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.IdentifiableBase; +import org.apache.maven.api.settings.Settings; import org.codehaus.plexus.util.StringUtils; /** @@ -40,66 +44,47 @@ public class MavenSettingsMerger * @param recessive * @param recessiveSourceLevel */ - public void merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) + public Settings merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) { - if ( dominant == null || recessive == null ) + if ( dominant == null ) { - return; + return recessive; + } + else if ( recessive == null ) + { + return dominant; } recessive.setSourceLevel( recessiveSourceLevel ); + Settings.Builder merged = Settings.newBuilder( dominant ); + List dominantActiveProfiles = dominant.getActiveProfiles(); List recessiveActiveProfiles = recessive.getActiveProfiles(); - - if ( recessiveActiveProfiles != null ) - { - if ( dominantActiveProfiles == null ) - { - dominantActiveProfiles = new ArrayList<>(); - dominant.setActiveProfiles( dominantActiveProfiles ); - } - - for ( String profileId : recessiveActiveProfiles ) - { - if ( !dominantActiveProfiles.contains( profileId ) ) - { - dominantActiveProfiles.add( profileId ); - } - } - } + List mergedActiveProfiles = Stream.of( dominantActiveProfiles, recessiveActiveProfiles ) + .flatMap( Collection::stream ) + .distinct() + .collect( Collectors.toList() ); + merged.activeProfiles( mergedActiveProfiles ); List dominantPluginGroupIds = dominant.getPluginGroups(); - List recessivePluginGroupIds = recessive.getPluginGroups(); - - if ( recessivePluginGroupIds != null ) - { - if ( dominantPluginGroupIds == null ) - { - dominantPluginGroupIds = new ArrayList<>(); - dominant.setPluginGroups( dominantPluginGroupIds ); - } - - for ( String pluginGroupId : recessivePluginGroupIds ) - { - if ( !dominantPluginGroupIds.contains( pluginGroupId ) ) - { - dominantPluginGroupIds.add( pluginGroupId ); - } - } - } - - if ( StringUtils.isEmpty( dominant.getLocalRepository() ) ) - { - dominant.setLocalRepository( recessive.getLocalRepository() ); - } - - shallowMergeById( dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel ); - shallowMergeById( dominant.getServers(), recessive.getServers(), recessiveSourceLevel ); - shallowMergeById( dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel ); - shallowMergeById( dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel ); - + List mergedPluginGroupIds = Stream.of( dominantPluginGroupIds, recessivePluginGroupIds ) + .flatMap( Collection::stream ) + .distinct() + .collect( Collectors.toList() ); + merged.pluginGroups( mergedPluginGroupIds ); + + String localRepository = StringUtils.isEmpty( dominant.getLocalRepository() ) + ? recessive.getLocalRepository() : dominant.getLocalRepository(); + merged.localRepository( localRepository ); + + merged.mirrors( shallowMergeById( dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel ) ); + merged.servers( shallowMergeById( dominant.getServers(), recessive.getServers(), recessiveSourceLevel ) ); + merged.proxies( shallowMergeById( dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel ) ); + merged.profiles( shallowMergeById( dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel ) ); + + return merged.build(); } /** @@ -107,23 +92,21 @@ public void merge( Settings dominant, Settings recessive, String recessiveSource * @param recessive * @param recessiveSourceLevel */ - private static void shallowMergeById( List dominant, List recessive, - String recessiveSourceLevel ) + private static List shallowMergeById( + List dominant, List recessive, String recessiveSourceLevel ) { - Map dominantById = mapById( dominant ); - final List identifiables = new ArrayList<>( recessive.size() ); - + Set dominantIds = dominant.stream().map( IdentifiableBase::getId ).collect( Collectors.toSet() ); + final List merged = new ArrayList<>( dominant.size() + recessive.size() ); + merged.addAll( dominant ); for ( T identifiable : recessive ) { - if ( !dominantById.containsKey( identifiable.getId() ) ) + if ( !dominantIds.contains( identifiable.getId() ) ) { identifiable.setSourceLevel( recessiveSourceLevel ); - - identifiables.add( identifiable ); + merged.add( identifiable ); } } - - dominant.addAll( 0, identifiables ); + return merged; } /** diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java index f0886421a3f6..05526df0ef3f 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java @@ -26,12 +26,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Repository; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Mirror; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; +import org.apache.maven.api.settings.Settings; import org.apache.maven.settings.building.SettingsProblem.Severity; import org.apache.maven.settings.building.SettingsProblemCollector; import org.codehaus.plexus.util.StringUtils; diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java index 79745ecaf14e..887229aa41cf 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; import org.apache.maven.settings.building.SettingsProblemCollector; /** diff --git a/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java b/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java index c23ebd2120de..0171af1019cb 100644 --- a/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java +++ b/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java @@ -20,14 +20,16 @@ */ import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Repository; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Mirror; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.Server; +import org.apache.maven.api.settings.Settings; import org.apache.maven.settings.building.SettingsProblem.Severity; import org.apache.maven.settings.building.SettingsProblemCollector; import org.junit.jupiter.api.AfterEach; @@ -67,26 +69,29 @@ private void assertContains( String msg, String substring ) @Test public void testValidate() { - Settings model = new Settings(); - Profile prof = new Profile(); - prof.setId( "xxx" ); - model.addProfile( prof ); + Profile prof = Profile.newInstance().withId( "xxx" ); + Settings model = Settings.newInstance().withProfiles( Collections.singletonList( prof ) ); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 0, problems.messages.size() ); - Repository repo = new Repository(); - prof.addRepository( repo ); + Repository repo = Repository.newInstance(); + prof = prof.withRepositories( Collections.singletonList( repo ) ); + model = model.withProfiles( Collections.singletonList( prof ) ); problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 2, problems.messages.size() ); - repo.setUrl( "http://xxx.xxx.com" ); + repo = repo.withUrl( "http://xxx.xxx.com" ); + prof = prof.withRepositories( Collections.singletonList( repo ) ); + model = model.withProfiles( Collections.singletonList( prof ) ); problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 1, problems.messages.size() ); - repo.setId( "xxx" ); + repo = repo.withId( "xxx" ); + prof = prof.withRepositories( Collections.singletonList( repo ) ); + model = model.withProfiles( Collections.singletonList( prof ) ); problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 0, problems.messages.size() ); @@ -96,15 +101,9 @@ public void testValidate() public void testValidateMirror() throws Exception { - Settings settings = new Settings(); - Mirror mirror = new Mirror(); - mirror.setId( "local" ); - settings.addMirror( mirror ); - mirror = new Mirror(); - mirror.setId( "illegal\\:/chars" ); - mirror.setUrl( "http://void" ); - mirror.setMirrorOf( "void" ); - settings.addMirror( mirror ); + Mirror mirror1 = Mirror.newBuilder().id( "local" ).build(); + Mirror mirror2 = Mirror.newBuilder().id( "illegal\\:/chars" ).url( "http://void" ).mirrorOf( "void" ).build(); + Settings settings = Settings.newBuilder().mirrors( Arrays.asList( mirror1, mirror2 ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -119,16 +118,10 @@ public void testValidateMirror() public void testValidateRepository() throws Exception { - Profile profile = new Profile(); - Repository repo = new Repository(); - repo.setId( "local" ); - profile.addRepository( repo ); - repo = new Repository(); - repo.setId( "illegal\\:/chars" ); - repo.setUrl( "http://void" ); - profile.addRepository( repo ); - Settings settings = new Settings(); - settings.addProfile( profile ); + Repository repo1 = Repository.newBuilder().id( "local" ).build(); + Repository repo2 = Repository.newBuilder().id( "illegal\\:/chars" ).url( "http://void" ).build(); + Profile profile = Profile.newBuilder().repositories( Arrays.asList( repo1, repo2 ) ).build(); + Settings settings = Settings.newBuilder().profiles( Collections.singletonList( profile ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -145,13 +138,9 @@ public void testValidateRepository() public void testValidateUniqueServerId() throws Exception { - Settings settings = new Settings(); - Server server1 = new Server(); - server1.setId( "test" ); - settings.addServer( server1 ); - Server server2 = new Server(); - server2.setId( "test" ); - settings.addServer( server2 ); + Server server1 = Server.newBuilder().id( "test" ).build(); + Server server2 = Server.newBuilder().id( "test" ).build(); + Settings settings = Settings.newBuilder().servers( Arrays.asList( server1, server2 ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -164,13 +153,9 @@ public void testValidateUniqueServerId() public void testValidateUniqueProfileId() throws Exception { - Settings settings = new Settings(); - Profile profile1 = new Profile(); - profile1.setId( "test" ); - settings.addProfile( profile1 ); - Profile profile2 = new Profile(); - profile2.setId( "test" ); - settings.addProfile( profile2 ); + Profile profile1 = Profile.newBuilder().id( "test" ).build(); + Profile profile2 = Profile.newBuilder().id( "test" ).build(); + Settings settings = Settings.newBuilder().profiles( Arrays.asList( profile1, profile2 ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -183,18 +168,10 @@ public void testValidateUniqueProfileId() public void testValidateUniqueRepositoryId() throws Exception { - Settings settings = new Settings(); - Profile profile = new Profile(); - profile.setId( "pro" ); - settings.addProfile( profile ); - Repository repo1 = new Repository(); - repo1.setUrl( "http://apache.org/" ); - repo1.setId( "test" ); - profile.addRepository( repo1 ); - Repository repo2 = new Repository(); - repo2.setUrl( "http://apache.org/" ); - repo2.setId( "test" ); - profile.addRepository( repo2 ); + Repository repo1 = Repository.newBuilder().id( "test" ).url( "http://apache.org/" ).build(); + Repository repo2 = Repository.newBuilder().id( "test" ).url( "http://apache.org/" ).build(); + Profile profile = Profile.newBuilder().id( "pro" ).repositories( Arrays.asList( repo1, repo2 ) ).build(); + Settings settings = Settings.newBuilder().profiles( Collections.singletonList( profile ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -205,21 +182,31 @@ public void testValidateUniqueRepositoryId() @Test public void testValidateUniqueProxyId() - throws Exception + throws Exception + { + Proxy proxy = Proxy.newBuilder().id( "foo" ).host( "www.example.com" ).build(); + Settings settings = Settings.newBuilder().proxies( Arrays.asList( proxy, proxy ) ).build(); + + SimpleProblemCollector problems = new SimpleProblemCollector(); + validator.validate( settings, problems ); + assertEquals( 1, problems.messages.size() ); + assertContains( problems.messages.get( 0 ), "'proxies.proxy.id' must be unique" + + " but found duplicate proxy with id foo" ); + + } + + @Test + public void testValidateUniqueProxyNullId() + throws Exception { - Settings settings = new Settings(); - Proxy proxy = new Proxy(); - String id = null; - proxy.setId( id ); - proxy.setHost("www.example.com"); - settings.addProxy( proxy ); - settings.addProxy( proxy ); + Proxy proxy = Proxy.newBuilder( false ).host( "www.example.com" ).build(); + Settings settings = Settings.newBuilder().proxies( Arrays.asList( proxy, proxy ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); assertEquals( 1, problems.messages.size() ); assertContains( problems.messages.get( 0 ), "'proxies.proxy.id' must be unique" - + " but found duplicate proxy with id " + id ); + + " but found duplicate proxy with id null" ); } @@ -227,9 +214,8 @@ public void testValidateUniqueProxyId() public void testValidateProxy() throws Exception { - Settings settings = new Settings(); - Proxy proxy1 = new Proxy(); - settings.addProxy( proxy1 ); + Proxy proxy = Proxy.newBuilder().build(); + Settings settings = Settings.newBuilder().proxies( Collections.singletonList( proxy ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index 4405e5c89799..2410260b5535 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -34,6 +34,16 @@ under the License. Maven Settings model. + + org.apache.maven + maven-api-settings + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT + org.codehaus.plexus plexus-utils @@ -43,14 +53,61 @@ under the License. - org.codehaus.modello - modello-maven-plugin - - 1.2.0 - - src/main/mdo/settings.mdo - - + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-model + generate-sources + + copy + + + + + org.apache.maven + maven-api-settings + 4.0.0-alpha-1-SNAPSHOT + mdo + target/mdo/ + settings.mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + + velocity + generate-sources + + velocity + + + 4.0.0 + + target/mdo/settings.mdo + + + + + + + + + packageModelV3=org.apache.maven.settings + packageModelV4=org.apache.maven.api.settings + packageToolV4=org.apache.maven.settings.v4 + + + + diff --git a/maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java b/maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java new file mode 100644 index 000000000000..83c3b5fab4ab --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java @@ -0,0 +1,129 @@ +package org.apache.maven.settings; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperList extends AbstractList +{ + private final Supplier> getter; + private final Consumer> setter; + private final Function mapper; + private final Function revMapper; + + WrapperList( List list, Function mapper, Function revMapper ) + { + this( () -> list, null, mapper, revMapper ); + } + + WrapperList( Supplier> getter, Consumer> setter, + Function mapper, Function revMapper ) + { + this.getter = getter; + this.setter = setter; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( getter.get().get( index ) ); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean add( T t ) + { + Objects.requireNonNull( t ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + boolean ret = list.add( revMapper.apply( t ) ); + setter.accept( list ); + return ret; + } + else + { + return getter.get().add( revMapper.apply( t ) ); + } + } + + @Override + public T set( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.set( index, revMapper.apply( element ) ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().set( index, revMapper.apply( element ) ) ); + } + } + + @Override + public void add( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + list.add( index, revMapper.apply( element ) ); + setter.accept( list ); + } + else + { + getter.get().add( index, revMapper.apply( element ) ); + } + } + + @Override + public T remove( int index ) + { + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.remove( index ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().remove( index ) ); + } + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java b/maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java new file mode 100644 index 000000000000..cd3ef0b84eaa --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java @@ -0,0 +1,356 @@ +package org.apache.maven.settings; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class WrapperProperties extends Properties +{ + + final Supplier getter; + final Consumer setter; + + public WrapperProperties( Supplier getter, Consumer setter ) + { + this.getter = getter; + this.setter = setter; + } + + @Override + public String getProperty( String key ) + { + return getter.get().getProperty( key ); + } + + @Override + public String getProperty( String key, String defaultValue ) + { + return getter.get().getProperty( key, defaultValue ); + } + + @Override + public Enumeration propertyNames() + { + return getter.get().propertyNames(); + } + + @Override + public Set stringPropertyNames() + { + return getter.get().stringPropertyNames(); + } + + @Override + public void list( PrintStream out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void list( PrintWriter out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean isEmpty() + { + return getter.get().isEmpty(); + } + + @Override + public Enumeration keys() + { + return getter.get().keys(); + } + + @Override + public Enumeration elements() + { + return getter.get().elements(); + } + + @Override + public boolean contains( Object value ) + { + return getter.get().contains( value ); + } + + @Override + public boolean containsValue( Object value ) + { + return getter.get().containsValue( value ); + } + + @Override + public boolean containsKey( Object key ) + { + return getter.get().containsKey( key ); + } + + @Override + public Object get( Object key ) + { + return getter.get().get( key ); + } + + @Override + public synchronized String toString() + { + return getter.get().toString(); + } + + @Override + public Set keySet() + { + return getter.get().keySet(); + } + + @Override + public Collection values() + { + return getter.get().values(); + } + + @Override + public Set> entrySet() + { + return getter.get().entrySet(); + } + + @Override + public synchronized boolean equals( Object o ) + { + if ( o instanceof WrapperProperties ) + { + o = ( (WrapperProperties) o ).getter.get(); + } + return getter.get().equals( o ); + } + + @Override + public synchronized int hashCode() + { + return getter.get().hashCode(); + } + + @Override + public Object getOrDefault( Object key, Object defaultValue ) + { + return getter.get().getOrDefault( key, defaultValue ); + } + + @Override + public synchronized void forEach( BiConsumer action ) + { + getter.get().forEach( action ); + } + + interface WriteOp + { + T perform( Properties props ); + } + + interface WriteOpVoid + { + void perform( Properties props ); + } + + private T writeOperation( WriteOp runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + T ret = runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + return ret; + } + + private void writeOperationVoid( WriteOpVoid runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + } + + @Override + public synchronized Object setProperty( String key, String value ) + { + return writeOperation( p -> p.setProperty( key, value ) ); + } + + @Override + public synchronized Object put( Object key, Object value ) + { + return writeOperation( p -> p.put( key, value ) ); + } + + @Override + public synchronized Object remove( Object key ) + { + return writeOperation( p -> p.remove( key ) ); + } + + @Override + public synchronized void putAll( Map t ) + { + writeOperationVoid( p -> p.putAll( t ) ); + } + + @Override + public synchronized void clear() + { + writeOperationVoid( Properties::clear ); + } + + @Override + public synchronized void replaceAll( BiFunction function ) + { + writeOperationVoid( p -> p.replaceAll( function ) ); + } + + @Override + public synchronized Object putIfAbsent( Object key, Object value ) + { + return writeOperation( p -> p.putIfAbsent( key, value ) ); + } + + @Override + public synchronized boolean remove( Object key, Object value ) + { + return writeOperation( p -> p.remove( key, value ) ); + } + + @Override + public synchronized boolean replace( Object key, Object oldValue, Object newValue ) + { + return writeOperation( p -> p.replace( key, oldValue, newValue ) ); + } + + @Override + public synchronized Object replace( Object key, Object value ) + { + return writeOperation( p -> p.replace( key, value ) ); + } + + @Override + public synchronized Object computeIfAbsent( Object key, Function mappingFunction ) + { + return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) ); + } + + @Override + public synchronized Object computeIfPresent( Object key, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) ); + } + + @Override + public synchronized Object compute( Object key, BiFunction remappingFunction ) + { + return writeOperation( p -> p.compute( key, remappingFunction ) ); + } + + @Override + public synchronized Object merge( Object key, Object value, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.merge( key, value, remappingFunction ) ); + } + + @Override + public synchronized void load( Reader reader ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void load( InputStream inStream ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void save( OutputStream out, String comments ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( Writer writer, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( OutputStream out, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException + { + throw new UnsupportedOperationException(); + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java new file mode 100644 index 000000000000..750a45f7cdce --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java @@ -0,0 +1,167 @@ +package org.apache.maven.settings.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import org.apache.maven.settings.Settings; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class SettingsXpp3Reader +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public SettingsXpp3Reader() + { + this( ( source, fieldName ) -> source ); + } + + public SettingsXpp3Reader( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities + ? new MXParser( EntityReplacementMap.defaultEntityReplacementMap ) : new MXParser(); + parser.setInput( reader ); + return read( parser, strict ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Settings read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + org.apache.maven.settings.v4.SettingsXpp3Reader reader = contentTransformer != null + ? new org.apache.maven.settings.v4.SettingsXpp3Reader( contentTransformer::transform ) + : new org.apache.maven.settings.v4.SettingsXpp3Reader(); + reader.setAddDefaultEntities( addDefaultEntities ); + org.apache.maven.api.settings.Settings settings = reader.read( parser, strict ); + return new Settings( settings ); + } //-- Model read( XmlPullParser, boolean ) + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java new file mode 100644 index 000000000000..c1710044046a --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java @@ -0,0 +1,84 @@ +package org.apache.maven.settings.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import org.apache.maven.settings.Settings; + +public class SettingsXpp3Writer +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param settings a settings object. + * @throws IOException java.io.IOException if any. + */ + public void write( Writer writer, Settings settings ) + throws IOException + { + org.apache.maven.settings.v4.SettingsXpp3Writer xw = new org.apache.maven.settings.v4.SettingsXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( writer, settings.getDelegate() ); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param settings a settings object. + * @throws IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Settings settings ) + throws IOException + { + org.apache.maven.settings.v4.SettingsXpp3Writer xw = new org.apache.maven.settings.v4.SettingsXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( stream, settings.getDelegate() ); + } //-- void write( OutputStream, Model ) + +} diff --git a/maven-settings/src/main/mdo/common.vm b/maven-settings/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/maven-settings/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm new file mode 100644 index 000000000000..e81c3baab302 --- /dev/null +++ b/maven-settings/src/main/mdo/merger.vm @@ -0,0 +1,380 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Merger" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * Merges the specified source object into the given target object. + * + * @param target The target object whose existing contents should be merged with the source, must not be + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @param sourceDominant A flag indicating whether either the target object or the source object provides the + * dominant data. + * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific + * information along, may be null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( !src.isEmpty() ) + { + Properties tgt = target.get${capField}(); + if ( tgt.isEmpty() ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm new file mode 100644 index 000000000000..fe38c72ebcdf --- /dev/null +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -0,0 +1,251 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV3}" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.allFields ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.AbstractList" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) ) + #set ( $dummy = $imports.add( "java.util.stream.Stream" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.codehaus.plexus.util.xml.Xpp3Dom" ) ) + #set ( $dummy = $types.put( $field, "Object" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable, Cloneable +{ + + #if ( ! $class.superClass ) + ${packageModelV4}.${class.name} delegate; + #end + + public ${class.name}() + { + this( ${packageModelV4}.${class.name}.newInstance() ); + } + + public ${class.name}( ${packageModelV4}.${class.name} delegate ) + { + #if ( $class.superClass ) + super( delegate ); + #else + this.delegate = delegate; + #end + } + + public ${class.name} clone() + { + return new ${class.name}( getDelegate() ); + } + + #if ( $class.superClass ) + @Override + #end + public ${packageModelV4}.${class.name} getDelegate() + { + #if ( $class.superClass ) + return ( ${packageModelV4}.${class.name} ) delegate; + #else + return delegate; + #end + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return Objects.equals( this.delegate, that.delegate ); + } + + @Override + public int hashCode() + { + return getDelegate().hashCode(); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return getDelegate().getModelEncoding(); + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( + getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), + ${field.to}::new, ${field.to}::getDelegate ); + #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + return new WrapperProperties( getDelegate()::get${cap}, this::set${cap} ); + #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList( getDelegate()::get${cap}, this::set${cap}, s -> s, s -> s ); + #elseif ( $field.to ) + return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}() ) : null; + #elseif ( $field.type == "DOM" ) + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; + #else + return getDelegate().${pfx}${cap}(); + #end + } + + public void set${cap}( ${type} ${field.name} ) + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + delegate = getDelegate().with${cap}( + ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ); + #elseif ( $field.to && $field.to != "String" ) + delegate = getDelegate().with${cap}( ${field.name}.getDelegate() ); + #elseif ( $field.type == "DOM" ) + delegate = getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ); + #else + delegate = getDelegate().with${cap}( ${field.name} ); + #end + } + + #if ( $field.type == "java.util.List" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( ${field.to} ${v} ) + { + #if ( $field.to == "String" ) + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) + .collect( Collectors.toList() ) ); + #else + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) + .collect( Collectors.toList() ) ); + #end + } + + #elseif ( $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( String key, String value ) + { + get${cap}().put( key, value ); + } + + #end + #end + public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + { + return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; + } + + public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List<${packageModelV4}.${class.name}> list ) + { + return list != null ? new WrapperList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm new file mode 100644 index 000000000000..a575b6534b94 --- /dev/null +++ b/maven-settings/src/main/mdo/reader.vm @@ -0,0 +1,899 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Reader" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, 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.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( ( s, f ) -> s ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + return getIntegerValue( s, attribute, parser, strict, 0 ); + } //-- int getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean, int ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#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 + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + List<$field.to> ${field.name} = new ArrayList<>(); + #end + #end + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = checkDuplicate( parser.getName(), parser, parsed ); + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #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}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}( ${field.name} ); + #end + #end + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String checkDuplicate( String tagName, XmlPullParser parser, Set parsed ) + throws XmlPullParserException + { +#set( $aliases = { } ) +#set( $flats = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular($fieldTagName) ) + #set ( $dummy = $flats.put( $fieldTagName, "" ) ) + #end + #end +#end +#if ( ! ${aliases.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + tagName = "${entry.value}"; + #end + } +#end +#if ( ! ${flats.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $flats.entrySet() ) + case "${entry.key}": + #end + break; + default: + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + } +#end + return tagName; + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm new file mode 100644 index 000000000000..e2740f45a4d3 --- /dev/null +++ b/maven-settings/src/main/mdo/writer.vm @@ -0,0 +1,331 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Writer" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#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 ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java index d1199873a6c7..78d76f6afe83 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java @@ -27,8 +27,8 @@ import org.apache.maven.toolchain.io.ToolchainsReader; import org.apache.maven.toolchain.io.ToolchainsWriter; import org.apache.maven.toolchain.merge.MavenToolchainMerger; -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.TrackableBase; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.TrackableBase; import org.codehaus.plexus.interpolation.EnvarBasedValueSource; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.RegexBasedInterpolator; @@ -76,11 +76,12 @@ public ToolchainsBuildingResult build( ToolchainsBuildingRequest request ) PersistedToolchains userToolchains = readToolchains( request.getUserToolchainsSource(), request, problems ); - toolchainsMerger.merge( userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL ); + PersistedToolchains merged = toolchainsMerger.merge( + userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL ); problems.setSource( "" ); - userToolchains = interpolate( userToolchains, problems ); + merged = interpolate( merged, problems ); if ( hasErrors( problems.getProblems() ) ) { @@ -88,7 +89,7 @@ public ToolchainsBuildingResult build( ToolchainsBuildingRequest request ) } - return new DefaultToolchainsBuildingResult( userToolchains, problems.getProblems() ); + return new DefaultToolchainsBuildingResult( merged, problems.getProblems() ); } private PersistedToolchains interpolate( PersistedToolchains toolchains, ProblemCollector problems ) @@ -160,7 +161,7 @@ private PersistedToolchains readToolchains( Source toolchainsSource, ToolchainsB { if ( toolchainsSource == null ) { - return new PersistedToolchains(); + return PersistedToolchains.newInstance(); } PersistedToolchains toolchains; @@ -187,13 +188,13 @@ private PersistedToolchains readToolchains( Source toolchainsSource, ToolchainsB { problems.add( Problem.Severity.FATAL, "Non-parseable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e ); - return new PersistedToolchains(); + return PersistedToolchains.newInstance(); } catch ( IOException e ) { problems.add( Problem.Severity.FATAL, "Non-readable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(), -1, -1, e ); - return new PersistedToolchains(); + return PersistedToolchains.newInstance(); } return toolchains; diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java index 2d07a4a03c29..c13ee8b65779 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java @@ -23,7 +23,7 @@ import java.util.List; import org.apache.maven.building.Problem; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Holds the result of the merged toolchains and holds the problems during this build, if any. diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java index f7c5f71554a8..0d91812148db 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java @@ -22,7 +22,7 @@ import java.util.List; import org.apache.maven.building.Problem; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Collects the output of the toolchains builder. diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java index 25225510fb28..b58995a69f34 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java @@ -29,8 +29,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java index 51ebdc7a9c41..a9ee7793b9fe 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; import javax.inject.Named; import javax.inject.Singleton; diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java index 44dc2bdc7902..413674a7b85e 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java @@ -25,7 +25,7 @@ import java.io.Reader; import java.util.Map; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Handles deserialization of toolchains from some kind of textual format like XML. diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java index 0b15f3451ad8..8e157cd45cd5 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; import java.io.IOException; import java.io.Writer; diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java index 9b6596ea3d38..d081bb52ca45 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java @@ -19,13 +19,14 @@ * under the License. */ +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.ToolchainModel; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.ToolchainModel; /** * @@ -35,19 +36,20 @@ public class MavenToolchainMerger { - public void merge( PersistedToolchains dominant, PersistedToolchains recessive, String recessiveSourceLevel ) + public PersistedToolchains merge( PersistedToolchains dominant, PersistedToolchains recessive, + String recessiveSourceLevel ) { if ( dominant == null || recessive == null ) { - return; + return dominant; } recessive.setSourceLevel( recessiveSourceLevel ); - shallowMerge( dominant.getToolchains(), recessive.getToolchains(), recessiveSourceLevel ); + return shallowMerge( dominant.getToolchains(), recessive.getToolchains(), recessiveSourceLevel ); } - private void shallowMerge( List dominant, List recessive, + private PersistedToolchains shallowMerge( List dominant, List recessive, String recessiveSourceLevel ) { Map merged = new LinkedHashMap<>(); @@ -67,32 +69,25 @@ private void shallowMerge( List dominant, List r if ( dominantModel == null ) { recessiveModel.setSourceLevel( recessiveSourceLevel ); - dominant.add( recessiveModel ); + merged.put( key, recessiveModel ); } else { - mergeToolchainModelConfiguration( dominantModel, recessiveModel ); + merged.put( key, mergeToolchainModelConfiguration( dominantModel, recessiveModel ) ); } } + return PersistedToolchains.newBuilder() + .toolchains( new ArrayList<>( merged.values() ) ) + .build(); } - protected void mergeToolchainModelConfiguration( ToolchainModel target, - ToolchainModel source ) + protected ToolchainModel mergeToolchainModelConfiguration( ToolchainModel target, + ToolchainModel source ) { - Xpp3Dom src = (Xpp3Dom) source.getConfiguration(); - if ( src != null ) - { - Xpp3Dom tgt = (Xpp3Dom) target.getConfiguration(); - if ( tgt == null ) - { - tgt = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( src ), tgt ); - } - else - { - tgt = Xpp3Dom.mergeXpp3Dom( tgt, src ); - } - target.setConfiguration( tgt ); - } + Dom src = source.getConfiguration(); + Dom tgt = target.getConfiguration(); + Dom merged = Dom.merge( tgt, src ); + return target.withConfiguration( merged ); } protected Object getToolchainModelKey( ToolchainModel model ) diff --git a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java index 6460aaf0a84e..a64b66af35a6 100644 --- a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java +++ b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java @@ -20,13 +20,13 @@ */ import org.apache.maven.building.StringSource; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.toolchain.io.DefaultToolchainsReader; import org.apache.maven.toolchain.io.DefaultToolchainsWriter; import org.apache.maven.toolchain.io.ToolchainsParseException; -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.ToolchainModel; import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; @@ -36,8 +36,10 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -87,11 +89,15 @@ public void testBuildRequestWithUserToolchains() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains userResult = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "user_value" ); - userResult.addToolchain( toolchain ); + Properties props = new Properties(); + props.put( "key", "user_value" ); + ToolchainModel toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .build(); + PersistedToolchains userResult = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); doReturn(userResult).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -110,11 +116,15 @@ public void testBuildRequestWithGlobalToolchains() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setGlobalToolchainsSource( new StringSource( "" ) ); - PersistedToolchains globalResult = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "global_value" ); - globalResult.addToolchain( toolchain ); + Properties props = new Properties(); + props.put( "key", "global_value" ); + ToolchainModel toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .build(); + PersistedToolchains globalResult = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); doReturn(globalResult).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -134,17 +144,26 @@ public void testBuildRequestWithBothToolchains() request.setGlobalToolchainsSource( new StringSource( "" ) ); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains userResult = new PersistedToolchains(); - ToolchainModel userToolchain = new ToolchainModel(); - userToolchain.setType( "TYPE" ); - userToolchain.addProvide( "key", "user_value" ); - userResult.addToolchain( userToolchain ); - - PersistedToolchains globalResult = new PersistedToolchains(); - ToolchainModel globalToolchain = new ToolchainModel(); - globalToolchain.setType( "TYPE" ); - globalToolchain.addProvide( "key", "global_value" ); - globalResult.addToolchain( globalToolchain ); + Properties props = new Properties(); + props.put( "key", "user_value" ); + ToolchainModel toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .build(); + PersistedToolchains userResult = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); + + props = new Properties(); + props.put( "key", "global_value" ); + toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .build(); + PersistedToolchains globalResult = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); + doReturn(globalResult).doReturn(userResult).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -203,17 +222,19 @@ public void testEnvironmentVariablesAreInterpolated() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains persistedToolchains = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "${env.testKey}" ); - - Xpp3Dom configurationChild = new Xpp3Dom("jdkHome"); - configurationChild.setValue("${env.testKey}"); - Xpp3Dom configuration = new Xpp3Dom("configuration"); - configuration.addChild(configurationChild); - toolchain.setConfiguration(configuration); - persistedToolchains.addToolchain( toolchain ); + Properties props = new Properties(); + props.put( "key", "${env.testKey}" ); + Xpp3Dom configurationChild = new Xpp3Dom("jdkHome", "${env.testKey}", null, null, null); + Xpp3Dom configuration = new Xpp3Dom("configuration", null, null, Collections.singletonList(configurationChild), null); + ToolchainModel toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .configuration( configuration ) + .build(); + PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); + doReturn(persistedToolchains).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -232,12 +253,16 @@ public void testNonExistingEnvironmentVariablesAreNotInterpolated() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains persistedToolchains = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "${env.testNonExistingKey}" ); + Properties props = new Properties(); + props.put( "key", "${env.testNonExistingKey}" ); + ToolchainModel toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .build(); + PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); - persistedToolchains.addToolchain( toolchain ); doReturn(persistedToolchains).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -253,12 +278,16 @@ public void testEnvironmentVariablesWithSpecialCharactersAreInterpolated() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains persistedToolchains = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "${env.testSpecialCharactersKey}" ); + Properties props = new Properties(); + props.put( "key", "${env.testSpecialCharactersKey}" ); + ToolchainModel toolchain = ToolchainModel.newBuilder() + .type( "TYPE" ) + .provides( props ) + .build(); + PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder() + .toolchains( Collections.singletonList( toolchain ) ) + .build(); - persistedToolchains.addToolchain( toolchain ); doReturn(persistedToolchains).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); diff --git a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java index 7bed9a909ad1..fec62506fa90 100644 --- a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java +++ b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java @@ -19,11 +19,11 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.ToolchainModel; -import org.apache.maven.toolchain.model.TrackableBase; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.api.toolchain.TrackableBase; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.junit.jupiter.api.Test; import java.io.InputStream; @@ -41,7 +41,7 @@ public void testMergeNulls() { merger.merge( null, null, null ); - PersistedToolchains pt = new PersistedToolchains(); + PersistedToolchains pt = PersistedToolchains.newInstance(); merger.merge( pt, null, null ); merger.merge( null, pt, null ); } @@ -50,15 +50,15 @@ public void testMergeNulls() public void testMergeJdk() throws Exception { - try ( InputStream isDominant = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream isRecessive = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ) ) + try ( InputStream isDominant = getClass().getResourceAsStream( "toolchains-jdks.xml" ); + InputStream isRecessive = getClass().getResourceAsStream( "toolchains-jdks.xml" ) ) { PersistedToolchains dominant = reader.read( isDominant ); PersistedToolchains recessive = reader.read( isRecessive ); assertEquals( 2, dominant.getToolchains().size() ); - merger.merge( dominant, recessive, TrackableBase.USER_LEVEL ); - assertEquals( 2, dominant.getToolchains().size() ); + PersistedToolchains merged = merger.merge( dominant, recessive, TrackableBase.USER_LEVEL ); + assertEquals( 2, merged.getToolchains().size() ); } } @@ -66,28 +66,32 @@ public void testMergeJdk() public void testMergeJdkExtra() throws Exception { - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtraIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extra.xml" ) ) + try ( InputStream jdksIS = getClass().getResourceAsStream( "toolchains-jdks.xml" ); + InputStream jdksExtraIS = getClass().getResourceAsStream( "toolchains-jdks-extra.xml" ) ) { PersistedToolchains jdks = reader.read( jdksIS ); PersistedToolchains jdksExtra = reader.read( jdksExtraIS ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtra.getToolchains().size() ); - merger.merge( jdks, jdksExtra, TrackableBase.USER_LEVEL ); - assertEquals( 4, jdks.getToolchains().size() ); + PersistedToolchains merged = merger.merge( jdks, jdksExtra, TrackableBase.USER_LEVEL ); + assertEquals( 4, merged.getToolchains().size() ); + assertEquals( 2, jdks.getToolchains().size() ); assertEquals( 2, jdksExtra.getToolchains().size() ); } - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtraIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extra.xml" ) ) + try ( InputStream jdksIS = getClass().getResourceAsStream( "toolchains-jdks.xml" ); + InputStream jdksExtraIS = getClass().getResourceAsStream( "toolchains-jdks-extra.xml" ) ) { PersistedToolchains jdks = reader.read( jdksIS ); PersistedToolchains jdksExtra = reader.read( jdksExtraIS ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtra.getToolchains().size() ); // switch dominant with recessive - merger.merge( jdksExtra, jdks, TrackableBase.USER_LEVEL ); - assertEquals( 4, jdksExtra.getToolchains().size() ); + PersistedToolchains merged = merger.merge( jdksExtra, jdks, TrackableBase.USER_LEVEL ); + assertEquals( 4, merged.getToolchains().size() ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtra.getToolchains().size() ); } } @@ -95,40 +99,42 @@ public void testMergeJdkExtra() public void testMergeJdkExtend() throws Exception { - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtendIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extend.xml" ) ) + try ( InputStream jdksIS = getClass().getResourceAsStream( "toolchains-jdks.xml" ); + InputStream jdksExtendIS = getClass().getResourceAsStream( "toolchains-jdks-extend.xml" ) ) { PersistedToolchains jdks = reader.read( jdksIS ); PersistedToolchains jdksExtend = reader.read( jdksExtendIS ); assertEquals( 2, jdks.getToolchains().size() ); - merger.merge( jdks, jdksExtend, TrackableBase.USER_LEVEL ); - assertEquals( 2, jdks.getToolchains().size() ); - Xpp3Dom config0 = (Xpp3Dom) jdks.getToolchains().get( 0 ).getConfiguration(); + PersistedToolchains merged = merger.merge( jdks, jdksExtend, TrackableBase.USER_LEVEL ); + assertEquals( 2, merged.getToolchains().size() ); + Dom config0 = merged.getToolchains().get( 0 ).getConfiguration(); assertEquals( "lib/tools.jar", config0.getChild( "toolsJar" ).getValue() ); - assertEquals( 2, config0.getChildCount() ); - Xpp3Dom config1 = (Xpp3Dom) jdks.getToolchains().get( 1 ).getConfiguration(); - assertEquals( 2, config1.getChildCount() ); + assertEquals( 2, config0.getChildren().size() ); + Dom config1 = merged.getToolchains().get( 1 ).getConfiguration(); + assertEquals( 2, config1.getChildren().size() ); assertEquals( "lib/classes.jar", config1.getChild( "toolsJar" ).getValue() ); + assertEquals( 2, jdks.getToolchains().size() ); assertEquals( 2, jdksExtend.getToolchains().size() ); } - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtendIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extend.xml" ) ) + try ( InputStream jdksIS = getClass().getResourceAsStream( "toolchains-jdks.xml" ); + InputStream jdksExtendIS = getClass().getResourceAsStream( "toolchains-jdks-extend.xml" ) ) { PersistedToolchains jdks = reader.read( jdksIS ); PersistedToolchains jdksExtend = reader.read( jdksExtendIS ); assertEquals( 2, jdks.getToolchains().size() ); // switch dominant with recessive - merger.merge( jdksExtend, jdks, TrackableBase.USER_LEVEL ); - assertEquals( 2, jdksExtend.getToolchains().size() ); - Xpp3Dom config0 = (Xpp3Dom) jdksExtend.getToolchains().get( 0 ).getConfiguration(); + PersistedToolchains merged = merger.merge( jdksExtend, jdks, TrackableBase.USER_LEVEL ); + assertEquals( 2, merged.getToolchains().size() ); + Dom config0 = merged.getToolchains().get( 0 ).getConfiguration(); assertEquals( "lib/tools.jar", config0.getChild( "toolsJar" ).getValue() ); - assertEquals( 2, config0.getChildCount() ); - Xpp3Dom config1 = (Xpp3Dom) jdksExtend.getToolchains().get( 1 ).getConfiguration(); - assertEquals( 2, config1.getChildCount() ); + assertEquals( 2, config0.getChildren().size() ); + Dom config1 = merged.getToolchains().get( 1 ).getConfiguration(); + assertEquals( 2, config1.getChildren().size() ); assertEquals( "lib/classes.jar", config1.getChild( "toolsJar" ).getValue() ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtend.getToolchains().size() ); } } diff --git a/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extend.xml b/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extend.xml similarity index 100% rename from maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extend.xml rename to maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extend.xml diff --git a/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extra.xml b/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extra.xml similarity index 100% rename from maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extra.xml rename to maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extra.xml diff --git a/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks.xml b/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks.xml similarity index 100% rename from maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks.xml rename to maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks.xml diff --git a/maven-toolchain-model/pom.xml b/maven-toolchain-model/pom.xml index cf3237136978..a0a8b0bdfc49 100644 --- a/maven-toolchain-model/pom.xml +++ b/maven-toolchain-model/pom.xml @@ -35,6 +35,16 @@ under the License. Maven Toolchain model. + + org.apache.maven + maven-api-toolchain + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT + org.codehaus.plexus plexus-utils @@ -44,14 +54,61 @@ under the License. - org.codehaus.modello - modello-maven-plugin - - 1.1.0 - - src/main/mdo/toolchains.mdo - - + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-model + generate-sources + + copy + + + + + org.apache.maven + maven-api-toolchain + 4.0.0-alpha-1-SNAPSHOT + mdo + target/mdo/ + toolchains.mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + + velocity + generate-sources + + velocity + + + 4.0.0 + + target/mdo/toolchains.mdo + + + + + + + + + packageModelV3=org.apache.maven.toolchain.model + packageModelV4=org.apache.maven.api.toolchain + packageToolV4=org.apache.maven.toolchain.v4 + + + + diff --git a/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java new file mode 100644 index 000000000000..5d6f7aa26842 --- /dev/null +++ b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java @@ -0,0 +1,129 @@ +package org.apache.maven.toolchain.model; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperList extends AbstractList +{ + private final Supplier> getter; + private final Consumer> setter; + private final Function mapper; + private final Function revMapper; + + WrapperList( List list, Function mapper, Function revMapper ) + { + this( () -> list, null, mapper, revMapper ); + } + + WrapperList( Supplier> getter, Consumer> setter, + Function mapper, Function revMapper ) + { + this.getter = getter; + this.setter = setter; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( getter.get().get( index ) ); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean add( T t ) + { + Objects.requireNonNull( t ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + boolean ret = list.add( revMapper.apply( t ) ); + setter.accept( list ); + return ret; + } + else + { + return getter.get().add( revMapper.apply( t ) ); + } + } + + @Override + public T set( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.set( index, revMapper.apply( element ) ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().set( index, revMapper.apply( element ) ) ); + } + } + + @Override + public void add( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + list.add( index, revMapper.apply( element ) ); + setter.accept( list ); + } + else + { + getter.get().add( index, revMapper.apply( element ) ); + } + } + + @Override + public T remove( int index ) + { + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.remove( index ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().remove( index ) ); + } + } + +} diff --git a/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java new file mode 100644 index 000000000000..f3bc6c5ff380 --- /dev/null +++ b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java @@ -0,0 +1,356 @@ +package org.apache.maven.toolchain.model; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class WrapperProperties extends Properties +{ + + final Supplier getter; + final Consumer setter; + + public WrapperProperties( Supplier getter, Consumer setter ) + { + this.getter = getter; + this.setter = setter; + } + + @Override + public String getProperty( String key ) + { + return getter.get().getProperty( key ); + } + + @Override + public String getProperty( String key, String defaultValue ) + { + return getter.get().getProperty( key, defaultValue ); + } + + @Override + public Enumeration propertyNames() + { + return getter.get().propertyNames(); + } + + @Override + public Set stringPropertyNames() + { + return getter.get().stringPropertyNames(); + } + + @Override + public void list( PrintStream out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void list( PrintWriter out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean isEmpty() + { + return getter.get().isEmpty(); + } + + @Override + public Enumeration keys() + { + return getter.get().keys(); + } + + @Override + public Enumeration elements() + { + return getter.get().elements(); + } + + @Override + public boolean contains( Object value ) + { + return getter.get().contains( value ); + } + + @Override + public boolean containsValue( Object value ) + { + return getter.get().containsValue( value ); + } + + @Override + public boolean containsKey( Object key ) + { + return getter.get().containsKey( key ); + } + + @Override + public Object get( Object key ) + { + return getter.get().get( key ); + } + + @Override + public synchronized String toString() + { + return getter.get().toString(); + } + + @Override + public Set keySet() + { + return getter.get().keySet(); + } + + @Override + public Collection values() + { + return getter.get().values(); + } + + @Override + public Set> entrySet() + { + return getter.get().entrySet(); + } + + @Override + public synchronized boolean equals( Object o ) + { + if ( o instanceof WrapperProperties ) + { + o = ( (WrapperProperties) o ).getter.get(); + } + return getter.get().equals( o ); + } + + @Override + public synchronized int hashCode() + { + return getter.get().hashCode(); + } + + @Override + public Object getOrDefault( Object key, Object defaultValue ) + { + return getter.get().getOrDefault( key, defaultValue ); + } + + @Override + public synchronized void forEach( BiConsumer action ) + { + getter.get().forEach( action ); + } + + interface WriteOp + { + T perform( Properties props ); + } + + interface WriteOpVoid + { + void perform( Properties props ); + } + + private T writeOperation( WriteOp runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + T ret = runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + return ret; + } + + private void writeOperationVoid( WriteOpVoid runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + } + + @Override + public synchronized Object setProperty( String key, String value ) + { + return writeOperation( p -> p.setProperty( key, value ) ); + } + + @Override + public synchronized Object put( Object key, Object value ) + { + return writeOperation( p -> p.put( key, value ) ); + } + + @Override + public synchronized Object remove( Object key ) + { + return writeOperation( p -> p.remove( key ) ); + } + + @Override + public synchronized void putAll( Map t ) + { + writeOperationVoid( p -> p.putAll( t ) ); + } + + @Override + public synchronized void clear() + { + writeOperationVoid( Properties::clear ); + } + + @Override + public synchronized void replaceAll( BiFunction function ) + { + writeOperationVoid( p -> p.replaceAll( function ) ); + } + + @Override + public synchronized Object putIfAbsent( Object key, Object value ) + { + return writeOperation( p -> p.putIfAbsent( key, value ) ); + } + + @Override + public synchronized boolean remove( Object key, Object value ) + { + return writeOperation( p -> p.remove( key, value ) ); + } + + @Override + public synchronized boolean replace( Object key, Object oldValue, Object newValue ) + { + return writeOperation( p -> p.replace( key, oldValue, newValue ) ); + } + + @Override + public synchronized Object replace( Object key, Object value ) + { + return writeOperation( p -> p.replace( key, value ) ); + } + + @Override + public synchronized Object computeIfAbsent( Object key, Function mappingFunction ) + { + return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) ); + } + + @Override + public synchronized Object computeIfPresent( Object key, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) ); + } + + @Override + public synchronized Object compute( Object key, BiFunction remappingFunction ) + { + return writeOperation( p -> p.compute( key, remappingFunction ) ); + } + + @Override + public synchronized Object merge( Object key, Object value, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.merge( key, value, remappingFunction ) ); + } + + @Override + public synchronized void load( Reader reader ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void load( InputStream inStream ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void save( OutputStream out, String comments ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( Writer writer, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( OutputStream out, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException + { + throw new UnsupportedOperationException(); + } + +} diff --git a/maven-toolchain-model/src/main/mdo/common.vm b/maven-toolchain-model/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm new file mode 100644 index 000000000000..e81c3baab302 --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -0,0 +1,380 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Merger" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * Merges the specified source object into the given target object. + * + * @param target The target object whose existing contents should be merged with the source, must not be + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @param sourceDominant A flag indicating whether either the target object or the source object provides the + * dominant data. + * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific + * information along, may be null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( !src.isEmpty() ) + { + Properties tgt = target.get${capField}(); + if ( tgt.isEmpty() ) + { + builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm new file mode 100644 index 000000000000..fe38c72ebcdf --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -0,0 +1,251 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageModelV3}" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +# +#foreach ( $class in $model.allClasses ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #set ( $inheritedFields = [] ) + #foreach ( $cl in $ancestors ) + #if ( $cl != $class ) + #set ( $dummy = $inheritedFields.addAll( $cl.allFields ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #set ( $types = { } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.AbstractList" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.List" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) ) + #set ( $dummy = $imports.add( "java.util.stream.Stream" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.codehaus.plexus.util.xml.Xpp3Dom" ) ) + #set ( $dummy = $types.put( $field, "Object" ) ) + #else + #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) + #set ( $idx = $fieldType.lastIndexOf('.') ) + #if ( $idx > 0 ) + #set ( $dummy = $imports.add( $fieldType ) ) + #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) + #end + #end + #end + #set ( $eq = "" ) + #set ( $hc = "" ) + #foreach ( $field in $allFields ) + #if ( $field.identifier ) + #set ( $dummy = $imports.add( "java.util.Objects" ) ) + #set ( $dummy = $identifiers.add( $field ) ) + #if ( $eq == "" ) + #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) + #else + #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) + #end + #if ( $hc == "" ) + #set ( $hc = "${field.name}" ) + #else + #set ( $hc = "$hc, this.${field.name}" ) + #end + #end + #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable, Cloneable +{ + + #if ( ! $class.superClass ) + ${packageModelV4}.${class.name} delegate; + #end + + public ${class.name}() + { + this( ${packageModelV4}.${class.name}.newInstance() ); + } + + public ${class.name}( ${packageModelV4}.${class.name} delegate ) + { + #if ( $class.superClass ) + super( delegate ); + #else + this.delegate = delegate; + #end + } + + public ${class.name} clone() + { + return new ${class.name}( getDelegate() ); + } + + #if ( $class.superClass ) + @Override + #end + public ${packageModelV4}.${class.name} getDelegate() + { + #if ( $class.superClass ) + return ( ${packageModelV4}.${class.name} ) delegate; + #else + return delegate; + #end + } + + #if ( ! $eq.empty ) + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || !( o instanceof ${class.name} ) ) + { + return false; + } + ${class.name} that = ( ${class.name} ) o; + return Objects.equals( this.delegate, that.delegate ); + } + + @Override + public int hashCode() + { + return getDelegate().hashCode(); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return getDelegate().getModelEncoding(); + } + + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == "boolean" || $type == "Boolean" ) + #set ( $pfx = "is" ) + #else + #set ( $pfx = "get" ) + #end + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) + @Nonnull + #end + public ${type} ${pfx}${cap}() + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( + getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), + ${field.to}::new, ${field.to}::getDelegate ); + #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + return new WrapperProperties( getDelegate()::get${cap}, this::set${cap} ); + #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList( getDelegate()::get${cap}, this::set${cap}, s -> s, s -> s ); + #elseif ( $field.to ) + return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}() ) : null; + #elseif ( $field.type == "DOM" ) + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; + #else + return getDelegate().${pfx}${cap}(); + #end + } + + public void set${cap}( ${type} ${field.name} ) + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + delegate = getDelegate().with${cap}( + ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ); + #elseif ( $field.to && $field.to != "String" ) + delegate = getDelegate().with${cap}( ${field.name}.getDelegate() ); + #elseif ( $field.type == "DOM" ) + delegate = getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ); + #else + delegate = getDelegate().with${cap}( ${field.name} ); + #end + } + + #if ( $field.type == "java.util.List" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( ${field.to} ${v} ) + { + #if ( $field.to == "String" ) + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) + .collect( Collectors.toList() ) ); + #else + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) + .collect( Collectors.toList() ) ); + #end + } + + #elseif ( $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( String key, String value ) + { + get${cap}().put( key, value ); + } + + #end + #end + public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + { + return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; + } + + public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List<${packageModelV4}.${class.name}> list ) + { + return list != null ? new WrapperList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm new file mode 100644 index 000000000000..a575b6534b94 --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -0,0 +1,899 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Reader" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, 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.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( ( s, f ) -> s ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + return getIntegerValue( s, attribute, parser, strict, 0 ); + } //-- int getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean, int ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#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 + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + List<$field.to> ${field.name} = new ArrayList<>(); + #end + #end + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = checkDuplicate( parser.getName(), parser, parsed ); + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #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}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}( ${field.name} ); + #end + #end + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String checkDuplicate( String tagName, XmlPullParser parser, Set parsed ) + throws XmlPullParserException + { +#set( $aliases = { } ) +#set( $flats = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular($fieldTagName) ) + #set ( $dummy = $flats.put( $fieldTagName, "" ) ) + #end + #end +#end +#if ( ! ${aliases.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + tagName = "${entry.value}"; + #end + } +#end +#if ( ! ${flats.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $flats.entrySet() ) + case "${entry.key}": + #end + break; + default: + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + } +#end + return tagName; + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm new file mode 100644 index 000000000000..e2740f45a4d3 --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -0,0 +1,331 @@ +#* + 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. +*# +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}Xpp3Writer" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${packageModelV4}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#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 ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-xml-impl/pom.xml b/maven-xml-impl/pom.xml new file mode 100644 index 000000000000..37933fabf395 --- /dev/null +++ b/maven-xml-impl/pom.xml @@ -0,0 +1,54 @@ + + + + + + + maven + org.apache.maven + 4.0.0-alpha-1-SNAPSHOT + + 4.0.0 + + maven-xml-impl + + Maven XML Implementation + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + org.eclipse.sisu + org.eclipse.sisu.plexus + + + org.codehaus.plexus + plexus-utils + ${plexusUtilsVersionEmbedded} + provided + + + + diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java new file mode 100644 index 000000000000..a4b14e728b6e --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java @@ -0,0 +1,93 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.Reader; + +//import org.apache.maven.api.model.InputLocation; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class DomBuilder +{ + + public static Xpp3Dom build( Reader reader ) + throws MavenXmlException + { + return build( reader, true ); + } + + public static Xpp3Dom build( Reader reader, boolean trim ) + throws MavenXmlException + { + try + { + MXParser parser = new MXParser(); + parser.setInput( reader ); + return build( parser, trim ); + } + catch ( XmlPullParserException e ) + { + throw new MavenXmlException( "Unable to build DOM", e ); + } + } + + public static Xpp3Dom build( XmlPullParser parser ) + { + return build( parser, true, null ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim ) + { + return build( parser, trim, null ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim, LocationBuilder locationBuilder ) + { + try + { + Xpp3DomBuilder.InputLocationBuilder ilb = + locationBuilder != null ? ( p -> locationBuilder.getLocation() ) : null; + return Xpp3DomBuilder.build( parser, trim, ilb ); + } + catch ( Exception e ) + { + throw new MavenXmlException( "Unable to build DOM", e ); + } + } + + public static class LocationBuilder + { + + private final Object location; + + public LocationBuilder( Object location ) + { + this.location = location; + } + + public Object getLocation() + { + return location; + } + } + +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java new file mode 100644 index 000000000000..7c251eeecd5f --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java @@ -0,0 +1,47 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +public class MavenXmlException extends RuntimeException +{ + public MavenXmlException() + { + } + + public MavenXmlException( String message ) + { + super( message ); + } + + public MavenXmlException( String message, Throwable cause ) + { + super( message, cause ); + } + + public MavenXmlException( Throwable cause ) + { + super( cause ); + } + + public MavenXmlException( String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace ) + { + super( message, cause, enableSuppression, writableStackTrace ); + } +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java new file mode 100644 index 000000000000..d215105b01e9 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java @@ -0,0 +1,68 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.configuration.DefaultPlexusConfiguration; +import org.codehaus.plexus.configuration.PlexusConfiguration; + +public class XmlPlexusConfiguration extends DefaultPlexusConfiguration +{ + public static PlexusConfiguration toPlexusConfiguration( Dom node ) + { + return new XmlPlexusConfiguration( node ); + } + + public XmlPlexusConfiguration( Dom node ) + { + super( node.getName(), node.getValue() ); + node.getAttributes().forEach( this::setAttribute ); + node.getChildren().forEach( c -> this.addChild( new XmlPlexusConfiguration( c ) ) ); + } + + @Override + public String toString() + { + final StringBuilder buf = new StringBuilder().append( '<' ).append( getName() ); + for ( final String a : getAttributeNames() ) + { + buf.append( ' ' ).append( a ).append( "=\"" ).append( getAttribute( a ) ).append( '"' ); + } + if ( getChildCount() > 0 ) + { + buf.append( '>' ); + for ( int i = 0, size = getChildCount(); i < size; i++ ) + { + buf.append( getChild( i ) ); + } + buf.append( "' ); + } + else if ( null != getValue() ) + { + buf.append( '>' ).append( getValue() ).append( "' ); + } + else + { + buf.append( "/>" ); + } + return buf.append( '\n' ).toString(); + } + +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java new file mode 100644 index 000000000000..05f7e597a764 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java @@ -0,0 +1,466 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.Serializable; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.SerializerXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +/** + * NOTE: remove all the util code in here when separated, this class should be pure data. + */ +public class Xpp3Dom + implements Serializable, Dom +{ + private static final long serialVersionUID = 2567894443061173996L; + + protected final String name; + + protected final String value; + + protected final Map attributes; + + protected final List children; + + protected final Object location; + + + public Xpp3Dom( String name ) + { + this( name, null, null, null, null ); + } + + public Xpp3Dom( String name, String value ) + { + this( name, value, null, null, null ); + } + + public Xpp3Dom( Dom from, String name ) + { + this( name, from.getValue(), from.getAttributes(), + from.getChildren(), from.getInputLocation() ); + } + + public Xpp3Dom( String name, String value, + Map attributes, + List children, + Object location ) + { + this.name = Objects.requireNonNull( name ); + this.value = value; + this.attributes = attributes != null + ? Collections.unmodifiableMap( new HashMap<>( attributes ) ) + : Collections.emptyMap(); + this.children = children != null + ? Collections.unmodifiableList( new ArrayList<>( children ) ) + : Collections.emptyList(); + this.location = location; + } + + @Override + public Dom merge( Dom source, Boolean childMergeOverride ) + { + return merge( this, source, childMergeOverride ); + } + + public Dom clone() + { + return this; + } + + // ---------------------------------------------------------------------- + // Name handling + // ---------------------------------------------------------------------- + + public String getName() + { + return name; + } + + // ---------------------------------------------------------------------- + // Value handling + // ---------------------------------------------------------------------- + + public String getValue() + { + return value; + } + + // ---------------------------------------------------------------------- + // Attribute handling + // ---------------------------------------------------------------------- + + @Override + public Map getAttributes() + { + return attributes; + } + + public String getAttribute( String name ) + { + return attributes.get( name ); + } + + // ---------------------------------------------------------------------- + // Child handling + // ---------------------------------------------------------------------- + + public Dom getChild( String name ) + { + if ( name != null ) + { + ListIterator it = children.listIterator( children.size() ); + while ( it.hasPrevious() ) + { + Dom child = it.previous(); + if ( name.equals( child.getName() ) ) + { + return child; + } + } + } + return null; + } + + public List getChildren() + { + return children; + } + + public int getChildCount() + { + return children.size(); + } + + // ---------------------------------------------------------------------- + // Input location handling + // ---------------------------------------------------------------------- + + /** + * @since 3.2.0 + * @return input location + */ + public Object getInputLocation() + { + return location; + } + + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + + public void writeToSerializer( String namespace, XmlSerializer serializer ) + throws IOException + { + // TODO: WARNING! Later versions of plexus-utils psit out an header due to thinking this is a new + // document - not the desired behaviour! + SerializerXMLWriter xmlWriter = new SerializerXMLWriter( namespace, serializer ); + Xpp3DomWriter.write( xmlWriter, this ); + if ( xmlWriter.getExceptions().size() > 0 ) + { + throw (IOException) xmlWriter.getExceptions().get( 0 ); + } + } + + /** + * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.

+ * The algorithm is as follows: + *

    + *
  1. if the recessive DOM is null, there is nothing to do... return.
  2. + *
  3. Determine whether the dominant node will suppress the recessive one (flag=mergeSelf). + *
      + *
    1. retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'... + * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one + * completely.
    2. + *
    3. otherwise, use the default value for mergeSelf, which is true...this is the same as specifying + * 'combine.self' == 'merge' as an attribute of the dominant root node.
    4. + *
  4. + *
  5. If mergeSelf == true + *
      + *
    1. if the dominant root node's value is empty, set it to the recessive root node's value
    2. + *
    3. For each attribute in the recessive root node which is not set in the dominant root node, set it.
    4. + *
    5. Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as + * siblings (flag=mergeChildren). + *
        + *
      1. if childMergeOverride is set (non-null), use that value (true/false)
      2. + *
      3. retrieve the 'combine.children' attribute on the dominant node, and try to match against + * 'append'...
      4. + *
      5. if it matches 'append', then set mergeChildren == false...the recessive children will be appended as + * siblings of the dominant children.
      6. + *
      7. otherwise, use the default value for mergeChildren, which is true...this is the same as specifying + * 'combine.children' == 'merge' as an attribute on the dominant root node.
      8. + *
    6. + *
    7. Iterate through the recessive children, and: + *
        + *
      1. if mergeChildren == true and there is a corresponding dominant child (matched by element name), + * merge the two.
      2. + *
      3. otherwise, add the recessive child as a new child on the dominant root node.
      4. + *
    8. + *
  6. + *
+ */ + @SuppressWarnings( "checkstyle:MethodLength" ) + public static Dom merge( Dom dominant, Dom recessive, Boolean childMergeOverride ) + { + // TODO: share this as some sort of assembler, implement a walk interface? + if ( recessive == null ) + { + return dominant; + } + if ( dominant == null ) + { + return recessive; + } + + boolean mergeSelf = true; + + String selfMergeMode = dominant.getAttribute( SELF_COMBINATION_MODE_ATTRIBUTE ); + + if ( SELF_COMBINATION_OVERRIDE.equals( selfMergeMode ) ) + { + mergeSelf = false; + } + + if ( mergeSelf ) + { + + String value = null; + Object location = null; + Map attrs = null; + List children = null; + + if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) ) + { + value = recessive.getValue(); + location = recessive.getInputLocation(); + } + + for ( Map.Entry attr : recessive.getAttributes().entrySet() ) + { + String key = attr.getKey(); + if ( isEmpty( dominant.getAttribute( key ) ) && !SELF_COMBINATION_MODE_ATTRIBUTE.equals( key ) ) + { + if ( attrs == null ) + { + attrs = new HashMap<>(); + } + attrs.put( key, attr.getValue() ); + } + } + + if ( recessive.getChildren().size() > 0 ) + { + boolean mergeChildren = true; + if ( childMergeOverride != null ) + { + mergeChildren = childMergeOverride; + } + else + { + String childMergeMode = dominant.getAttribute( CHILDREN_COMBINATION_MODE_ATTRIBUTE ); + if ( CHILDREN_COMBINATION_APPEND.equals( childMergeMode ) ) + { + mergeChildren = false; + } + } + + if ( !mergeChildren ) + { + children = new ArrayList<>( recessive.getChildren().size() + dominant.getChildren().size() ); + children.addAll( recessive.getChildren() ); + children.addAll( dominant.getChildren() ); + } + else + { + Map> commonChildren = new HashMap<>(); + Set names = recessive.getChildren().stream() + .map( Dom::getName ).collect( Collectors.toSet() ); + for ( String name : names ) + { + List dominantChildren = dominant.getChildren().stream() + .filter( n -> n.getName().equals( name ) ) + .collect( Collectors.toList() ); + if ( dominantChildren.size() > 0 ) + { + commonChildren.put( name, dominantChildren.iterator() ); + } + } + + for ( Dom recessiveChild : recessive.getChildren() ) + { + String name = recessiveChild.getName(); + Iterator it = commonChildren.computeIfAbsent( name, + n1 -> Stream.of( dominant.getChildren().stream() + .filter( n2 -> n2.getName().equals( n1 ) ) + .collect( Collectors.toList() ) ) + .filter( l -> !l.isEmpty() ) + .map( List::iterator ) + .findFirst() + .orElse( null ) ); + if ( it == null ) + { + if ( children == null ) + { + children = new ArrayList<>( dominant.getChildren() ); + } + children.add( recessiveChild ); + } + else if ( it.hasNext() ) + { + Dom dominantChild = it.next(); + + String dominantChildCombinationMode = + dominantChild.getAttribute( SELF_COMBINATION_MODE_ATTRIBUTE ); + if ( SELF_COMBINATION_REMOVE.equals( dominantChildCombinationMode ) ) + { + if ( children == null ) + { + children = new ArrayList<>( dominant.getChildren() ); + } + children.remove( dominantChild ); + } + else + { + int idx = ( children != null ? children : dominant.getChildren() ) + .indexOf( dominantChild ); + Dom merged = merge( dominantChild, recessiveChild, childMergeOverride ); + if ( merged != dominantChild ) + { + if ( children == null ) + { + children = new ArrayList<>( dominant.getChildren() ); + } + children.set( idx, merged ); + } + } + } + } + } + } + + if ( value != null || attrs != null || children != null ) + { + if ( attrs != null ) + { + Map nattrs = attrs; + attrs = new HashMap<>( dominant.getAttributes() ); + attrs.putAll( nattrs ); + } + else + { + attrs = dominant.getAttributes(); + } + if ( children == null ) + { + children = dominant.getChildren(); + } + return new Xpp3Dom( dominant.getName(), value != null ? value : dominant.getValue(), + attrs, children, location ); + } + } + return dominant; + } + + /** + * Merge two DOMs, with one having dominance in the case of collision. Merge mechanisms (vs. override for nodes, or + * vs. append for children) is determined by attributes of the dominant root node. + * + * @see #CHILDREN_COMBINATION_MODE_ATTRIBUTE + * @see #SELF_COMBINATION_MODE_ATTRIBUTE + * @param dominant The dominant DOM into which the recessive value/attributes/children will be merged + * @param recessive The recessive DOM, which will be merged into the dominant DOM + * @return merged DOM + */ + public static Dom merge( Dom dominant, Dom recessive ) + { + return merge( dominant, recessive, null ); + } + + // ---------------------------------------------------------------------- + // Standard object handling + // ---------------------------------------------------------------------- + + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + Xpp3Dom xpp3Dom = (Xpp3Dom) o; + return name.equals( xpp3Dom.name ) && Objects.equals( value, xpp3Dom.value ) && attributes.equals( + xpp3Dom.attributes ) && children.equals( xpp3Dom.children ); + } + + @Override + public int hashCode() + { + return Objects.hash( name, value, attributes, children ); + } + + @Override + public String toString() + { + StringWriter writer = new StringWriter(); + Xpp3DomWriter.write( writer, this ); + return writer.toString(); + } + + public String toUnescapedString() + { + StringWriter writer = new StringWriter(); + XMLWriter xmlWriter = new PrettyPrintXMLWriter( writer ); + Xpp3DomWriter.write( xmlWriter, this, false ); + return writer.toString(); + } + + public static boolean isNotEmpty( String str ) + { + return ( ( str != null ) && ( str.length() > 0 ) ); + } + + public static boolean isEmpty( String str ) + { + return ( ( str == null ) || ( str.trim().length() == 0 ) ); + } + +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java new file mode 100644 index 000000000000..ee50ab7b4af1 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java @@ -0,0 +1,215 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * + */ +public class Xpp3DomBuilder +{ + private static final boolean DEFAULT_TRIM = true; + + public static Xpp3Dom build( Reader reader ) + throws XmlPullParserException, IOException + { + return build( reader, null ); + } + + /** + * @param reader the reader + * @param locationBuilder the builder + * @since 3.2.0 + * @return DOM + * @throws XmlPullParserException xml exception + * @throws IOException io + */ + public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return build( reader, DEFAULT_TRIM, locationBuilder ); + } + + public static Xpp3Dom build( InputStream is, String encoding ) + throws XmlPullParserException, IOException + { + return build( is, encoding, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( InputStream is, String encoding, boolean trim ) + throws XmlPullParserException, IOException + { + try + { + final XmlPullParser parser = new MXParser(); + parser.setInput( is, encoding ); + + final Xpp3Dom xpp3Dom = build( parser, trim ); + is.close(); + is = null; + + return xpp3Dom; + } + finally + { + IOUtil.close( is ); + } + } + + public static Xpp3Dom build( Reader reader, boolean trim ) + throws XmlPullParserException, IOException + { + return build( reader, trim, null ); + } + + /** + * @param reader the reader + * @param trim to trim + * @param locationBuilder the builder + * @since 3.2.0 + * @return DOM + * @throws XmlPullParserException xml exception + * @throws IOException io + */ + public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + try + { + final XmlPullParser parser = new MXParser(); + parser.setInput( reader ); + + final Xpp3Dom xpp3Dom = build( parser, trim, locationBuilder ); + reader.close(); + reader = null; + + return xpp3Dom; + } + finally + { + IOUtil.close( reader ); + } + } + + public static Xpp3Dom build( XmlPullParser parser ) + throws XmlPullParserException, IOException + { + return build( parser, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim ) + throws XmlPullParserException, IOException + { + return build( parser, trim, null ); + } + + /** + * @since 3.2.0 + * @param locationBuilder builder + * @param parser the parser + * @param trim do trim + * @return DOM + * @throws XmlPullParserException xml exception + * @throws IOException io + */ + public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + boolean spacePreserve = false; + String name = null; + String value = null; + Object location = null; + Map attrs = null; + List children = null; + int eventType = parser.getEventType(); + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( name == null ) + { + name = parser.getName(); + location = locationBuilder != null ? locationBuilder.toInputLocation( parser ) : null; + int attributesSize = parser.getAttributeCount(); + if ( attributesSize > 0 ) + { + attrs = new HashMap<>(); + for ( int i = 0; i < attributesSize; i++ ) + { + String aname = parser.getAttributeName( i ); + String avalue = parser.getAttributeValue( i ); + attrs.put( aname, avalue ); + spacePreserve = + spacePreserve || ( "xml:space".equals( aname ) && "preserve".equals( avalue ) ); + } + } + } + else + { + if ( children == null ) + { + children = new ArrayList<>(); + } + Dom child = build( parser, trim, locationBuilder ); + children.add( child ); + } + } + else if ( eventType == XmlPullParser.TEXT ) + { + String text = parser.getText(); + if ( trim && !spacePreserve ) + { + text = text.trim(); + } + value = value != null ? value + text : text; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + return new Xpp3Dom( name, children == null ? value : null, + attrs, children, location ); + } + eventType = parser.next(); + } + throw new IllegalStateException( "End of document found before returning to 0 depth" ); + } + + /** + * Input location builder interface, to be implemented to choose how to store data. + * + * @since 3.2.0 + */ + public interface InputLocationBuilder + { + Object toInputLocation( XmlPullParser parser ); + } +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java new file mode 100644 index 000000000000..7000752ce669 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java @@ -0,0 +1,79 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Map; + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * + */ +public class Xpp3DomWriter +{ + public static void write( Writer writer, Dom dom ) + { + write( new PrettyPrintXMLWriter( writer ), dom ); + } + + public static void write( PrintWriter writer, Dom dom ) + { + write( new PrettyPrintXMLWriter( writer ), dom ); + } + + public static void write( XMLWriter xmlWriter, Dom dom ) + { + write( xmlWriter, dom, true ); + } + + public static void write( XMLWriter xmlWriter, Dom dom, boolean escape ) + { + // TODO: move to XMLWriter? + xmlWriter.startElement( dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + xmlWriter.addAttribute( attr.getKey(), attr.getValue() ); + } + for ( Dom aChildren : dom.getChildren() ) + { + write( xmlWriter, aChildren, escape ); + } + + String value = dom.getValue(); + if ( value != null ) + { + if ( escape ) + { + xmlWriter.writeText( value ); + } + else + { + xmlWriter.writeMarkup( value ); + } + } + + xmlWriter.endElement(); + } + +} diff --git a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java new file mode 100644 index 000000000000..5718e07fcd9b --- /dev/null +++ b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java @@ -0,0 +1,488 @@ +package org.codehaus.plexus.util.xml; + +/* + * 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. + */ + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * NOTE: remove all the util code in here when separated, this class should be pure data. + */ +public class Xpp3Dom + implements Serializable +{ + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final Xpp3Dom[] EMPTY_DOM_ARRAY = new Xpp3Dom[0]; + + public static final String CHILDREN_COMBINATION_MODE_ATTRIBUTE = "combine.children"; + + public static final String CHILDREN_COMBINATION_MERGE = "merge"; + + public static final String CHILDREN_COMBINATION_APPEND = "append"; + + /** + * This default mode for combining children DOMs during merge means that where element names match, the process will + * try to merge the element data, rather than putting the dominant and recessive elements (which share the same + * element name) as siblings in the resulting DOM. + */ + public static final String DEFAULT_CHILDREN_COMBINATION_MODE = CHILDREN_COMBINATION_MERGE; + + public static final String SELF_COMBINATION_MODE_ATTRIBUTE = "combine.self"; + + public static final String SELF_COMBINATION_OVERRIDE = "override"; + + public static final String SELF_COMBINATION_MERGE = "merge"; + + public static final String SELF_COMBINATION_REMOVE = "remove"; + + /** + * This default mode for combining a DOM node during merge means that where element names match, the process will + * try to merge the element attributes and values, rather than overriding the recessive element completely with the + * dominant one. This means that wherever the dominant element doesn't provide the value or a particular attribute, + * that value or attribute will be set from the recessive DOM node. + */ + public static final String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE; + + private ChildrenTracking childrenTracking; + private Dom dom; + + public Xpp3Dom( String name ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( name ); + } + + /** + * @since 3.2.0 + * @param inputLocation The input location. + * @param name The name of the Dom. + */ + public Xpp3Dom( String name, Object inputLocation ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( name, null, null, null, inputLocation ); + } + + /** + * Copy constructor. + * @param src The source Dom. + */ + public Xpp3Dom( Xpp3Dom src ) + { + this( src, src.getName() ); + } + + /** + * Copy constructor with alternative name. + * @param src The source Dom. + * @param name The name of the Dom. + */ + public Xpp3Dom( Xpp3Dom src, String name ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( src.dom, name ); + } + + public Xpp3Dom( Dom dom ) + { + this.dom = dom; + } + + public Xpp3Dom( Dom dom, Xpp3Dom parent ) + { + this.dom = dom; + this.childrenTracking = parent::replace; + } + + public Xpp3Dom( Dom dom, ChildrenTracking childrenTracking ) + { + this.dom = dom; + this.childrenTracking = childrenTracking; + } + + public Dom getDom() + { + return dom; + } + + // ---------------------------------------------------------------------- + // Name handling + // ---------------------------------------------------------------------- + + public String getName() + { + return dom.getName(); + } + + // ---------------------------------------------------------------------- + // Value handling + // ---------------------------------------------------------------------- + + public String getValue() + { + return dom.getValue(); + } + + public void setValue( String value ) + { + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), value, dom.getAttributes(), dom.getChildren(), dom.getInputLocation() ) ); + } + + // ---------------------------------------------------------------------- + // Attribute handling + // ---------------------------------------------------------------------- + + public String[] getAttributeNames() + { + return dom.getAttributes().keySet().toArray( EMPTY_STRING_ARRAY ); + } + + public String getAttribute( String name ) + { + return dom.getAttribute( name ); + } + + /** + * + * @param name name of the attribute to be removed + * @return true if the attribute has been removed + * @since 3.4.0 + */ + public boolean removeAttribute( String name ) + { + if ( ! StringUtils.isEmpty( name ) ) + { + Map attrs = new HashMap<>( dom.getAttributes() ); + boolean ret = attrs.remove( name ) != null; + if ( ret ) + { + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ) ); + } + return ret; + } + return false; + } + + /** + * Set the attribute value + * + * @param name String not null + * @param value String not null + */ + public void setAttribute( String name, String value ) + { + if ( null == value ) + { + throw new NullPointerException( "Attribute value can not be null" ); + } + if ( null == name ) + { + throw new NullPointerException( "Attribute name can not be null" ); + } + Map attrs = new HashMap<>( dom.getAttributes() ); + attrs.put( name, value ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ) ); + } + + // ---------------------------------------------------------------------- + // Child handling + // ---------------------------------------------------------------------- + + public Xpp3Dom getChild( int i ) + { + return new Xpp3Dom( dom.getChildren().get( i ), this ); + } + + public Xpp3Dom getChild( String name ) + { + Dom child = dom.getChild( name ); + return child != null ? new Xpp3Dom( child, this ) : null; + } + + public void addChild( Xpp3Dom xpp3Dom ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.add( xpp3Dom.dom ); + xpp3Dom.childrenTracking = this::replace; + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); + } + + public Xpp3Dom[] getChildren() + { + return dom.getChildren().stream() + .map( d -> new Xpp3Dom( d, this ) ).toArray( Xpp3Dom[]::new ); + } + + public Xpp3Dom[] getChildren( String name ) + { + return dom.getChildren().stream() + .filter( c -> c.getName().equals( name ) ) + .map( d -> new Xpp3Dom( d, this ) ).toArray( Xpp3Dom[]::new ); + } + + public int getChildCount() + { + return dom.getChildren().size(); + } + + public void removeChild( int i ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.remove( i ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); + } + + public void removeChild( Xpp3Dom child ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.remove( child.dom ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); + } + + // ---------------------------------------------------------------------- + // Parent handling + // ---------------------------------------------------------------------- + + public Xpp3Dom getParent() + { + throw new UnsupportedOperationException(); + } + + public void setParent( Xpp3Dom parent ) + { + } + + // ---------------------------------------------------------------------- + // Input location handling + // ---------------------------------------------------------------------- + + /** + * @since 3.2.0 + * @return input location + */ + public Object getInputLocation() + { + return dom.getInputLocation(); + } + + /** + * @since 3.2.0 + * @param inputLocation input location to set + */ + public void setInputLocation( Object inputLocation ) + { + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), dom.getChildren(), inputLocation ) ); + } + + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + + public void writeToSerializer( String namespace, XmlSerializer serializer ) + throws IOException + { + // TODO: WARNING! Later versions of plexus-utils psit out an header due to thinking this is a new + // document - not the desired behaviour! + SerializerXMLWriter xmlWriter = new SerializerXMLWriter( namespace, serializer ); + Xpp3DomWriter.write( xmlWriter, this ); + if ( xmlWriter.getExceptions().size() > 0 ) + { + throw (IOException) xmlWriter.getExceptions().get( 0 ); + } + } + + /** + * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.

+ * The algorithm is as follows: + *

    + *
  1. if the recessive DOM is null, there is nothing to do... return.
  2. + *
  3. Determine whether the dominant node will suppress the recessive one (flag=mergeSelf). + *
      + *
    1. retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'... + * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one + * completely.
    2. + *
    3. otherwise, use the default value for mergeSelf, which is true...this is the same as specifying + * 'combine.self' == 'merge' as an attribute of the dominant root node.
    4. + *
  4. + *
  5. If mergeSelf == true + *
      + *
    1. if the dominant root node's value is empty, set it to the recessive root node's value
    2. + *
    3. For each attribute in the recessive root node which is not set in the dominant root node, set it.
    4. + *
    5. Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as + * siblings (flag=mergeChildren). + *
        + *
      1. if childMergeOverride is set (non-null), use that value (true/false)
      2. + *
      3. retrieve the 'combine.children' attribute on the dominant node, and try to match against + * 'append'...
      4. + *
      5. if it matches 'append', then set mergeChildren == false...the recessive children will be appended as + * siblings of the dominant children.
      6. + *
      7. otherwise, use the default value for mergeChildren, which is true...this is the same as specifying + * 'combine.children' == 'merge' as an attribute on the dominant root node.
      8. + *
    6. + *
    7. Iterate through the recessive children, and: + *
        + *
      1. if mergeChildren == true and there is a corresponding dominant child (matched by element name), + * merge the two.
      2. + *
      3. otherwise, add the recessive child as a new child on the dominant root node.
      4. + *
    8. + *
  6. + *
+ */ + private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride ) + { + // TODO: share this as some sort of assembler, implement a walk interface? + if ( recessive == null ) + { + return; + } + dominant.dom = dominant.dom.merge( recessive.dom, childMergeOverride ); + } + + /** + * Merge two DOMs, with one having dominance in the case of collision. + * + * @see #CHILDREN_COMBINATION_MODE_ATTRIBUTE + * @see #SELF_COMBINATION_MODE_ATTRIBUTE + * @param dominant The dominant DOM into which the recessive value/attributes/children will be merged + * @param recessive The recessive DOM, which will be merged into the dominant DOM + * @param childMergeOverride Overrides attribute flags to force merging or appending of child elements into the + * dominant DOM + * @return merged DOM + */ + public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride ) + { + if ( dominant != null ) + { + mergeIntoXpp3Dom( dominant, recessive, childMergeOverride ); + return dominant; + } + return recessive; + } + + /** + * Merge two DOMs, with one having dominance in the case of collision. Merge mechanisms (vs. override for nodes, or + * vs. append for children) is determined by attributes of the dominant root node. + * + * @see #CHILDREN_COMBINATION_MODE_ATTRIBUTE + * @see #SELF_COMBINATION_MODE_ATTRIBUTE + * @param dominant The dominant DOM into which the recessive value/attributes/children will be merged + * @param recessive The recessive DOM, which will be merged into the dominant DOM + * @return merged DOM + */ + public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive ) + { + if ( dominant != null ) + { + mergeIntoXpp3Dom( dominant, recessive, null ); + return dominant; + } + return recessive; + } + + // ---------------------------------------------------------------------- + // Standard object handling + // ---------------------------------------------------------------------- + + @Override + public boolean equals( Object obj ) + { + if ( obj == this ) + { + return true; + } + + if ( !( obj instanceof Xpp3Dom ) ) + { + return false; + } + + Xpp3Dom dom = (Xpp3Dom) obj; + return this.dom.equals( dom.dom ); + } + + @Override + public int hashCode() + { + return dom.hashCode(); + } + + @Override + public String toString() + { + return dom.toString(); + } + + public String toUnescapedString() + { + return ( ( Xpp3Dom ) dom ).toUnescapedString(); + } + + public static boolean isNotEmpty( String str ) + { + return ( ( str != null ) && ( str.length() > 0 ) ); + } + + public static boolean isEmpty( String str ) + { + return ( ( str == null ) || ( str.trim().length() == 0 ) ); + } + + private void update( Dom dom ) + { + if ( childrenTracking != null ) + { + childrenTracking.replace( this.dom, dom ); + } + this.dom = dom; + } + + private boolean replace( Object prevChild, Object newChild ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.replaceAll( d -> d == prevChild ? ( Dom ) newChild : d ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); + return true; + } + + public void setChildrenTracking( ChildrenTracking childrenTracking ) + { + this.childrenTracking = childrenTracking; + } + + @FunctionalInterface + public interface ChildrenTracking + { + boolean replace( Object oldDelegate, Object newDelegate ); + } +} diff --git a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java new file mode 100644 index 000000000000..bdcfc4e454f5 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java @@ -0,0 +1,110 @@ +package org.codehaus.plexus.util.xml; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * @version $Id$ + */ +public class Xpp3DomBuilder +{ + private static final boolean DEFAULT_TRIM = true; + + public static Xpp3Dom build( Reader reader ) + throws XmlPullParserException, IOException + { + return build( reader, null ); + } + + /** + * @since 3.2.0 + */ + public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return build( reader, DEFAULT_TRIM, locationBuilder ); + } + + public static Xpp3Dom build( InputStream is, String encoding ) + throws XmlPullParserException, IOException + { + return build( is, encoding, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( InputStream is, String encoding, boolean trim ) + throws XmlPullParserException, IOException + { + return new Xpp3Dom( org.apache.maven.internal.xml.Xpp3DomBuilder.build( is, encoding, trim ) ); + } + + public static Xpp3Dom build( Reader reader, boolean trim ) + throws XmlPullParserException, IOException + { + return build( reader, trim, null ); + } + + /** + * @since 3.2.0 + */ + public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return new Xpp3Dom( org.apache.maven.internal.xml.Xpp3DomBuilder.build( + reader, trim, locationBuilder != null ? locationBuilder::toInputLocation : null ) ); + } + + public static Xpp3Dom build( XmlPullParser parser ) + throws XmlPullParserException, IOException + { + return build( parser, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim ) + throws XmlPullParserException, IOException + { + return build( parser, trim, null ); + } + + /** + * @since 3.2.0 + */ + public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return new Xpp3Dom( org.apache.maven.internal.xml.Xpp3DomBuilder.build( + parser, trim, locationBuilder != null ? locationBuilder::toInputLocation : null ) ); + } + + /** + * Input location builder interface, to be implemented to choose how to store data. + * + * @since 3.2.0 + */ + public interface InputLocationBuilder + { + Object toInputLocation( XmlPullParser parser ); + } +} diff --git a/plexus-utils/pom.xml b/plexus-utils/pom.xml new file mode 100644 index 000000000000..efbe9f8d8015 --- /dev/null +++ b/plexus-utils/pom.xml @@ -0,0 +1,172 @@ + + + + + + + maven + org.apache.maven + 4.0.0-alpha-1-SNAPSHOT + + 4.0.0 + + org.codehaus.plexus + plexus-utils + 4.0.0-alpha-1-SNAPSHOT + + + + org.codehaus.plexus + plexus-utils + ${plexusUtilsVersionEmbedded} + + + org.apache.maven + maven-xml-impl + ${project.version} + provided + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + unpack-sourcs + generate-sources + + unpack + + + + + org.codehaus.plexus + plexus-utils + ${plexusUtilsVersionEmbedded} + sources + jar + false + ${project.build.directory}/generated-sources/plexus-utils + **/*.java + + org/codehaus/plexus/util/xml/Xpp3Dom.java, + org/codehaus/plexus/util/xml/Xpp3DomBuilder.java + + + + + + + unpack-classes + process-classes + + unpack + + + + + org.codehaus.plexus + plexus-utils + ${plexusUtilsVersionEmbedded} + jar + false + ${project.build.directory}/classes + **/*.class,**/*.xml + + org/codehaus/plexus/util/xml/Xpp3Dom.class, + org/codehaus/plexus/util/xml/Xpp3DomBuilder.class + + + + org.apache.maven + maven-api-xml + ${project.version} + jar + **/* + ${project.build.directory}/classes + + + org.apache.maven + maven-xml-impl + ${project.version} + jar + **/* + ${project.build.directory}/classes + + + **/*.java + false + true + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + add-source + generate-sources + + add-source + + + + target/generated-sources/plexus-utils + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + + compile + + true + + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + + + check-java-compat + none + + + + + + + diff --git a/pom.xml b/pom.xml index 3ef430426d97..950f3f903400 100644 --- a/pom.xml +++ b/pom.xml @@ -55,7 +55,8 @@ under the License. 3.2.0 2.1.0 1.26 - 3.4.2 + 4.0.0-alpha-1-SNAPSHOT + 3.4.2 5.1.0 30.1-jre 1.0.1 @@ -82,6 +83,9 @@ under the License. maven-model maven-model-builder maven-model-transform + api + maven-xml-impl + plexus-utils maven-core maven-settings maven-settings-builder @@ -586,6 +590,7 @@ under the License. src/main/appended-resources/licenses/EPL-1.0.txt src/main/appended-resources/licenses/unrecognized-aopalliance-1.0.txt src/main/appended-resources/licenses/unrecognized-javax.annotation-api-1.3.2.txt + plexus-utils/target/** @@ -671,7 +676,8 @@ under the License. maven-checkstyle-plugin info - ${maven.multiModuleProjectDirectory}/build/checkstyle-suppressions.xml + JavadocVariable,JavadocMethod,HiddenField +