You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by gn...@apache.org on 2022/03/17 09:51:25 UTC

[maven] 03/03: Add support for reading/writing xml models

This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch mvn4
in repository https://gitbox.apache.org/repos/asf/maven.git

commit a036f07a6578543145c702038ff6811c4243ccc7
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Tue Mar 15 11:30:23 2022 +0100

    Add support for reading/writing xml models
---
 maven-core-api/pom.xml                             |   4 +
 .../maven/api/services/ToolchainFactory.java       |  25 +++
 .../maven/api/services/xml/ModelXmlFactory.java    |  27 +++
 .../maven/api/services/xml/SettingsXmlFactory.java |  27 +++
 .../api/services/xml/ToolchainsXmlFactory.java     |  27 +++
 .../apache/maven/api/services/xml/XmlFactory.java  |  72 +++++++
 .../maven/api/services/xml/XmlReaderException.java |  40 ++++
 .../maven/api/services/xml/XmlReaderRequest.java   | 222 +++++++++++++++++++++
 .../maven/api/services/xml/XmlWriterException.java |  40 ++++
 .../maven/api/services/xml/XmlWriterRequest.java   | 100 ++++++++++
 .../internal/impl/DefaultModelXmlFactory.java      | 115 +++++++++++
 .../apache/maven/internal/impl/DefaultSession.java |  15 ++
 .../internal/impl/DefaultSettingsXmlFactory.java   | 105 ++++++++++
 .../internal/impl/DefaultToolchainsXmlFactory.java | 105 ++++++++++
 14 files changed, 924 insertions(+)

diff --git a/maven-core-api/pom.xml b/maven-core-api/pom.xml
index 46af6de..77a9e51 100644
--- a/maven-core-api/pom.xml
+++ b/maven-core-api/pom.xml
@@ -38,6 +38,10 @@
       <groupId>org.apache.maven</groupId>
       <artifactId>maven-settings</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.apache.maven</groupId>
+      <artifactId>maven-toolchain-model</artifactId>
+    </dependency>
   </dependencies>
 
 </project>
diff --git a/maven-core-api/src/main/java/org/apache/maven/api/services/ToolchainFactory.java b/maven-core-api/src/main/java/org/apache/maven/api/services/ToolchainFactory.java
new file mode 100644
index 0000000..97db209
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/ToolchainFactory.java
@@ -0,0 +1,25 @@
+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.
+ */
+
+public interface ToolchainFactory
+{
+    // TODO: implement ToolchainFactory
+}
diff --git a/maven-core-api/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java
new file mode 100644
index 0000000..2fa88f5
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java
@@ -0,0 +1,27 @@
+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.model.Model;
+
+public interface ModelXmlFactory extends XmlFactory<Model>
+{
+
+}
diff --git a/maven-core-api/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java
new file mode 100644
index 0000000..a981588
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java
@@ -0,0 +1,27 @@
+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.settings.Settings;
+
+public interface SettingsXmlFactory extends XmlFactory<Settings>
+{
+
+}
diff --git a/maven-core-api/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java
new file mode 100644
index 0000000..a465ade
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java
@@ -0,0 +1,27 @@
+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.toolchain.model.PersistedToolchains;
+
+public interface ToolchainsXmlFactory extends XmlFactory<PersistedToolchains>
+{
+
+}
diff --git a/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java
new file mode 100644
index 0000000..a466533
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java
@@ -0,0 +1,72 @@
+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 org.apache.maven.api.annotations.Nonnull;
+import org.apache.maven.api.services.Service;
+
+public interface XmlFactory<T> extends Service
+{
+
+    @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 OutputStream outputStream ) throws XmlWriterException
+    {
+        write( XmlWriterRequest.<T>builder().content( content ).outputStream( outputStream ).build() );
+    }
+
+    default void write( @Nonnull T content, @Nonnull Writer writer ) throws XmlWriterException
+    {
+        write( XmlWriterRequest.<T>builder().content( content ).writer( writer ).build() );
+    }
+
+    void write( @Nonnull XmlWriterRequest<T> request ) throws XmlWriterException;
+
+}
diff --git a/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java
new file mode 100644
index 0000000..b5cd94c
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java
@@ -0,0 +1,40 @@
+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.services.MavenException;
+
+/**
+ * 
+ */
+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/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java
new file mode 100644
index 0000000..31a3068
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java
@@ -0,0 +1,222 @@
+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;
+
+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 );
+    }
+
+    static XmlReaderRequestBuilder builder()
+    {
+        return new XmlReaderRequestBuilder();
+    }
+
+    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/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java
new file mode 100644
index 0000000..6ac5f4c
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java
@@ -0,0 +1,40 @@
+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.services.MavenException;
+
+/**
+ * 
+ */
+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/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java
new file mode 100644
index 0000000..d504f44
--- /dev/null
+++ b/maven-core-api/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java
@@ -0,0 +1,100 @@
+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;
+
+public interface XmlWriterRequest<T>
+{
+
+    OutputStream getOutputStream();
+
+    Writer getWriter();
+
+    T getContent();
+
+    static <T> XmlWriterRequestBuilder<T> builder()
+    {
+        return new XmlWriterRequestBuilder<>();
+    }
+
+    class XmlWriterRequestBuilder<T>
+    {
+        OutputStream outputStream;
+        Writer writer;
+        T content;
+
+        public XmlWriterRequestBuilder<T> outputStream( OutputStream outputStream )
+        {
+            this.outputStream = outputStream;
+            return this;
+        }
+
+        public XmlWriterRequestBuilder<T> writer( Writer writer )
+        {
+            this.writer = writer;
+            return this;
+        }
+
+        public XmlWriterRequestBuilder<T> content( T content )
+        {
+            this.content = content;
+            return this;
+        }
+
+        public XmlWriterRequest<T> build()
+        {
+            return new DefaultXmlWriterRequest<>( outputStream, writer, content );
+        }
+
+        private static class DefaultXmlWriterRequest<T> implements XmlWriterRequest<T>
+        {
+            final OutputStream outputStream;
+            final Writer writer;
+            final T content;
+
+            DefaultXmlWriterRequest( OutputStream outputStream, Writer writer, T content )
+            {
+                this.outputStream = outputStream;
+                this.writer = writer;
+                this.content = content;
+            }
+
+            @Override
+            public OutputStream getOutputStream()
+            {
+                return outputStream;
+            }
+
+            @Override
+            public Writer getWriter()
+            {
+                return writer;
+            }
+
+            @Override
+            public T getContent()
+            {
+                return content;
+            }
+        }
+    }
+}
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 0000000..5dd8cdb
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java
@@ -0,0 +1,115 @@
+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.Path;
+import java.util.Objects;
+
+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.model.InputSource;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3ReaderEx;
+import org.apache.maven.model.io.xpp3.MavenXpp3WriterEx;
+import org.codehaus.plexus.util.ReaderFactory;
+
+public class DefaultModelXmlFactory
+        implements ModelXmlFactory
+{
+    @Override
+    public Model read( @Nonnull XmlReaderRequest request ) throws XmlReaderException
+    {
+        Objects.requireNonNull( 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();
+                source.setModelId( request.getModelId() );
+                source.setLocation( 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<Model> request ) throws XmlWriterException
+    {
+        Objects.requireNonNull( request, "request can not be null" );
+        Model 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 MavenXpp3WriterEx().write( writer, content );
+            }
+            else
+            {
+                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/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java
index 588f3f9..96f8a9a 100644
--- 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
@@ -53,6 +53,9 @@ import org.apache.maven.api.Project;
 import org.apache.maven.api.LocalRepository;
 import org.apache.maven.api.RemoteRepository;
 import org.apache.maven.api.services.ToolchainManager;
+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.artifact.repository.ArtifactRepository;
 import org.apache.maven.bridge.MavenRepositorySystem;
 import org.apache.maven.execution.MavenSession;
@@ -275,6 +278,18 @@ public class DefaultSession implements Session
         {
             return (T) new DefaultToolchainManager( toolchainManagerPrivate );
         }
+        else if ( clazz == ModelXmlFactory.class )
+        {
+            return (T) new DefaultModelXmlFactory();
+        }
+        else if ( clazz == SettingsXmlFactory.class )
+        {
+            return (T) new DefaultSettingsXmlFactory();
+        }
+        else if ( clazz == ToolchainsXmlFactory.class )
+        {
+            return (T) new DefaultToolchainsXmlFactory();
+        }
         throw new NoSuchElementException( clazz.getName() );
     }
 
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 0000000..d103ed3
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java
@@ -0,0 +1,105 @@
+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.model.InputSource;
+import org.apache.maven.settings.Settings;
+import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader;
+import org.apache.maven.settings.io.xpp3.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();
+                source.setModelId( request.getModelId() );
+                source.setLocation( 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<Settings> 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/DefaultToolchainsXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java
new file mode 100644
index 0000000..b837c6a
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java
@@ -0,0 +1,105 @@
+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.model.InputSource;
+import org.apache.maven.toolchain.model.PersistedToolchains;
+import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader;
+import org.apache.maven.toolchain.model.io.xpp3.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();
+                source.setModelId( request.getModelId() );
+                source.setLocation( 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<PersistedToolchains> 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 );
+        }
+    }
+}