From 8185fc01ad00d453ec38a235bbfd9a11b0617007 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 15 Jun 2023 13:30:17 +0200 Subject: [PATCH 1/6] [MNG-7814] Use location tracking for settings --- .../maven/settings/GlobalSettingsTest.java | 13 +- api/maven-api-settings/pom.xml | 1 + .../maven/api/settings/InputLocation.java | 172 +++ .../api/settings/InputLocationTracker.java | 23 + .../maven/api/settings/InputSource.java | 47 + .../src/main/mdo/settings.mdo | 52 +- .../impl/DefaultSettingsXmlFactory.java | 12 +- .../building/DefaultSettingsBuilder.java | 47 +- .../settings/io/DefaultSettingsReader.java | 12 +- maven-settings/pom.xml | 30 +- .../apache/maven/settings/InputLocation.java | 358 ++++++ .../maven/settings/InputLocationTracker.java | 52 + .../apache/maven/settings/InputSource.java | 99 ++ src/mdo/reader.vm | 1038 ++++++++--------- 14 files changed, 1399 insertions(+), 557 deletions(-) create mode 100644 api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java create mode 100644 api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java create mode 100644 api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/InputSource.java 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 9512d4a934e..a8819f87b60 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 @@ -19,12 +19,11 @@ package org.apache.maven.settings; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; +import java.io.InputStream; +import java.nio.file.Files; -import org.apache.maven.settings.v4.SettingsXpp3Reader; +import org.apache.maven.api.settings.InputSource; +import org.apache.maven.settings.v4.SettingsXpp3ReaderEx; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -43,8 +42,8 @@ void testValidGlobalSettings() throws Exception { File globalSettingsFile = new File(basedir, "src/assembly/maven/conf/settings.xml"); assertTrue(globalSettingsFile.isFile(), globalSettingsFile.getAbsolutePath()); - try (Reader reader = new InputStreamReader(new FileInputStream(globalSettingsFile), StandardCharsets.UTF_8)) { - new SettingsXpp3Reader().read(reader); + try (InputStream is = Files.newInputStream(globalSettingsFile.toPath())) { + new SettingsXpp3ReaderEx().read(is, true, new InputSource(globalSettingsFile.getAbsolutePath())); } } } diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml index 3a05752c600..db5265d2299 100644 --- a/api/maven-api-settings/pom.xml +++ b/api/maven-api-settings/pom.xml @@ -61,6 +61,7 @@ under the License. packageModelV4=org.apache.maven.api.settings + locationTracking=true diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java new file mode 100644 index 00000000000..b3ea387142b --- /dev/null +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocation.java @@ -0,0 +1,172 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.api.settings; + +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; + } + + /** + * Merges the {@code source} location into the {@code target} location. + * + * @param target the target location + * @param source the source location + * @param sourceDominant the boolean indicating of {@code source} is dominant compared to {@code target} + * @return the merged location + */ + 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 ) + + /** + * Merges the {@code source} location into the {@code target} location. + * This method is used when the locations refer to lists and also merges the indices. + * + * @param target the target location + * @param source the source location + * @param indices the list of integers for the indices + * @return the merged location + */ + 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-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java new file mode 100644 index 00000000000..d49d7230766 --- /dev/null +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputLocationTracker.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.api.settings; + +public interface InputLocationTracker { + InputLocation getLocation(Object field); +} diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java new file mode 100644 index 00000000000..c87c72a671e --- /dev/null +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.api.settings; + +import java.io.Serializable; + +/** + * Class InputSource. + */ +public class InputSource implements Serializable { + + private final String location; + + public InputSource(String location) { + this.location = location; + } + + /** + * Get the path/URL of the POM or {@code null} if unknown. + * + * @return the location + */ + public String getLocation() { + return this.location; + } + + @Override + public String toString() { + return getLocation(); + } +} diff --git a/api/maven-api-settings/src/main/mdo/settings.mdo b/api/maven-api-settings/src/main/mdo/settings.mdo index 9e9221aaa49..07699665b7d 100644 --- a/api/maven-api-settings/src/main/mdo/settings.mdo +++ b/api/maven-api-settings/src/main/mdo/settings.mdo @@ -265,7 +265,7 @@ - 1.0.0+ + 1.0.0/1.2.0 + + InputLocation + 4.0.0+ + + + + + + 4.0.0+ + + + + + + + + InputSource + 4.0.0+ + + + location + 4.0.0+ + String + + + + + + + + 4.0.0+ + + + + + + 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 index 39303e9cd0a..811fd3c6b21 100644 --- 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 @@ -28,14 +28,14 @@ import java.util.Objects; import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.model.InputSource; 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.settings.InputSource; import org.apache.maven.api.settings.Settings; -import org.apache.maven.settings.v4.SettingsXpp3Reader; +import org.apache.maven.settings.v4.SettingsXpp3ReaderEx; import org.apache.maven.settings.v4.SettingsXpp3Writer; @Named @@ -52,14 +52,14 @@ public Settings read(@Nonnull XmlReaderRequest request) throws XmlReaderExceptio try { InputSource source = null; if (request.getModelId() != null || request.getLocation() != null) { - source = new InputSource(request.getModelId(), request.getLocation()); + source = new InputSource(request.getLocation()); } - SettingsXpp3Reader xml = new SettingsXpp3Reader(); + SettingsXpp3ReaderEx xml = new SettingsXpp3ReaderEx(); xml.setAddDefaultEntities(request.isAddDefaultEntities()); if (reader != null) { - return xml.read(reader, request.isStrict()); + return xml.read(reader, request.isStrict(), source); } else { - return xml.read(inputStream, request.isStrict()); + return xml.read(inputStream, request.isStrict(), source); } } catch (Exception e) { throw new XmlReaderException("Unable to read settings", e); 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 67acbafac9b..50710f553b3 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 @@ -24,12 +24,12 @@ import java.io.File; import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.maven.api.settings.InputSource; import org.apache.maven.building.FileSource; import org.apache.maven.building.Source; import org.apache.maven.settings.Settings; @@ -38,6 +38,7 @@ import org.apache.maven.settings.io.SettingsReader; import org.apache.maven.settings.io.SettingsWriter; import org.apache.maven.settings.merge.MavenSettingsMerger; +import org.apache.maven.settings.v4.SettingsTransformer; import org.apache.maven.settings.validation.SettingsValidator; import org.codehaus.plexus.interpolation.EnvarBasedValueSource; import org.codehaus.plexus.interpolation.InterpolationException; @@ -149,8 +150,9 @@ private Settings readSettings( Settings settings; try { - Map options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.TRUE); - + Map options = new HashMap<>(); + options.put(SettingsReader.IS_STRICT, Boolean.TRUE); + options.put(InputSource.class.getName(), new InputSource(settingsSource.getLocation())); try { settings = settingsReader.read(settingsSource.getInputStream(), options); } catch (SettingsParseException e) { @@ -186,15 +188,6 @@ private Settings readSettings( private Settings interpolate( Settings settings, SettingsBuildingRequest request, SettingsProblemCollector problems) { - StringWriter writer = new StringWriter(1024 * 4); - - try { - settingsWriter.write(writer, null, settings); - } catch (IOException e) { - throw new IllegalStateException("Failed to serialize settings to memory", e); - } - - String serializedSettings = writer.toString(); RegexBasedInterpolator interpolator = new RegexBasedInterpolator(); @@ -213,6 +206,22 @@ private Settings interpolate( e); } + return new Settings(new SettingsTransformer(value -> { + try { + return interpolator.interpolate(value); + } catch (InterpolationException e) { + problems.add( + SettingsProblem.Severity.WARNING, + "Failed to interpolate settings: " + e.getMessage(), + -1, + -1, + e); + return value; + } + }) + .visit(settings.getDelegate())); + + /* interpolator.addPostProcessor((expression, value) -> { if (value != null) { // we're going to parse this back in as XML so we need to escape XML markup @@ -225,6 +234,16 @@ private Settings interpolate( return null; }); + StringWriter writer = new StringWriter(1024 * 4); + + try { + settingsWriter.write(writer, null, settings); + } catch (IOException e) { + throw new IllegalStateException("Failed to serialize settings to memory", e); + } + + String serializedSettings = writer.toString(); + try { serializedSettings = interpolator.interpolate(serializedSettings, "settings"); } catch (InterpolationException e) { @@ -245,5 +264,7 @@ private Settings interpolate( } return result; + + */ } } 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 fc96ad1a23c..a30e2bbd213 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,9 @@ import java.util.Map; import java.util.Objects; +import org.apache.maven.api.settings.InputSource; import org.apache.maven.settings.Settings; -import org.apache.maven.settings.v4.SettingsXpp3Reader; +import org.apache.maven.settings.v4.SettingsXpp3ReaderEx; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** @@ -47,7 +48,8 @@ public Settings read(File input, Map options) throws IOException { Objects.requireNonNull(input, "input cannot be null"); try (InputStream in = Files.newInputStream(input.toPath())) { - return new Settings(new SettingsXpp3Reader().read(in, isStrict(options))); + InputSource source = new InputSource(input.toString()); + return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source)); } catch (XmlPullParserException e) { throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } @@ -58,7 +60,8 @@ public Settings read(Reader input, Map options) throws IOException { Objects.requireNonNull(input, "input cannot be null"); try (Reader in = input) { - return new Settings(new SettingsXpp3Reader().read(in, isStrict(options))); + InputSource source = (InputSource) options.get(InputSource.class.getName()); + return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source)); } catch (XmlPullParserException e) { throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } @@ -69,7 +72,8 @@ public Settings read(InputStream input, Map options) throws IOExcepti Objects.requireNonNull(input, "input cannot be null"); try (InputStream in = input) { - return new Settings(new SettingsXpp3Reader().read(in, isStrict(options))); + InputSource source = (InputSource) options.get(InputSource.class.getName()); + return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source)); } catch (XmlPullParserException e) { throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index c27963e9410..8afaee377dc 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -54,12 +54,17 @@ under the License. org.codehaus.modello modello-maven-plugin - 2.0.0 ${project.basedir}/../api/maven-api-settings ${project.basedir}/../src/mdo src/main/mdo/settings.mdo + + packageModelV3=org.apache.maven.settings + packageModelV4=org.apache.maven.api.settings + packageToolV4=org.apache.maven.settings.v4 + locationTracking=true + @@ -69,17 +74,28 @@ under the License. generate-sources + 2.0.0 - + + + + + + + + v3 + + velocity + + generate-sources + + 1.2.0 + + - - 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/InputLocation.java b/maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java new file mode 100644 index 00000000000..8e7cbae6208 --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java @@ -0,0 +1,358 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.settings; + +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.settings.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.settings.InputLocation toApiLocation() { + if (locations != null && locations.values().contains(this)) { + if (locations.size() == 1 && locations.values().iterator().next() == this) { + return new org.apache.maven.api.settings.InputLocation( + lineNumber, + columnNumber, + source != null ? source.toApiSource() : null, + locations.keySet().iterator().next()); + } else { + return new org.apache.maven.api.settings.InputLocation( + lineNumber, columnNumber, source != null ? source.toApiSource() : null); + } + } else { + return new org.apache.maven.api.settings.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-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java b/maven-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java new file mode 100644 index 00000000000..e65408c1491 --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.settings; + +/** + * 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-settings/src/main/java/org/apache/maven/settings/InputSource.java b/maven-settings/src/main/java/org/apache/maven/settings/InputSource.java new file mode 100644 index 00000000000..0112a8b5074 --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/InputSource.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.maven.settings; + +/** + * Class InputSource. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings("all") +public class InputSource implements java.io.Serializable, Cloneable { + + // --------------------------/ + // - Class/Member Variables -/ + // --------------------------/ + + /** + * + * + * The path/URL of the POM or {@code null} if + * unknown. + * + * + */ + private String location; + + // ----------------/ + // - Constructors -/ + // ----------------/ + + public InputSource() {} + + public InputSource(org.apache.maven.api.settings.InputSource source) { + 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() + + /** + * 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 ) + + @Override + public String toString() { + return getLocation(); + } + + public org.apache.maven.api.settings.InputSource toApiSource() { + return new org.apache.maven.api.settings.InputSource(location); + } +} diff --git a/src/mdo/reader.vm b/src/mdo/reader.vm index b95ea612838..a1b86af1d50 100644 --- a/src/mdo/reader.vm +++ b/src/mdo/reader.vm @@ -74,305 +74,595 @@ public class ${className} { } /** - * Method checkFieldWithDuplicate. + * @see ReaderFactory#newXmlReader * - * @param parser a parser object. - * @param parsed a parsed object. - * @param alias a alias object. - * @param tagName a tagName object. + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return boolean + * @return ${root.name} */ - 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) + 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) /** - * Method checkUnknownAttribute. + * @see ReaderFactory#newXmlReader * - * @param parser a parser object. - * @param strict a strict object. - * @param tagName a tagName object. - * @param attribute a attribute object. + * @param reader a reader object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @throws IOException IOException if any. + * @return ${root.name} */ - 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) + public ${root.name} read(Reader reader) throws IOException, XmlPullParserException { + return read(reader, true); + } //-- ${root.name} read(Reader) /** - * Method checkUnknownElement. + * Method read. * - * @param parser a parser object. + * @param in a in 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 + * @return ${root.name} */ - private boolean getBooleanValue(String s, String attribute, XmlPullParser parser) - throws XmlPullParserException { - return getBooleanValue(s, attribute, parser, false); - } //-- boolean getBooleanValue(String, String, XmlPullParser) + public ${root.name} read(InputStream in, boolean strict) throws IOException, XmlPullParserException { + return read(ReaderFactory.newXmlReader(in), strict); + } //-- ${root.name} read(InputStream, boolean) /** - * Method getBooleanValue. + * Method read. * - * @param s a s object. - * @param defaultValue a defaultValue object. - * @param parser a parser object. - * @param attribute a attribute object. + * @param in a in object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return boolean + * @return ${root.name} */ - 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) + public ${root.name} read(InputStream in) throws IOException, XmlPullParserException { + return read(ReaderFactory.newXmlReader(in)); + } //-- ${root.name} read(InputStream) /** - * Method getByteValue. + * Method read. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return byte + * @return ${root.name} */ - 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); + 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(); } - 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); + if (parsed) { + return $rootLcapName; } - 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) + throw new XmlPullParserException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null); + } //-- ${root.name} read(XmlPullParser, boolean) - /** - * 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"; +#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 } - 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); - } + #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); } } - 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); + 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}(XmlNodeBuilder.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 == "*" ) + Map ${field.name} = new LinkedHashMap<>(); + 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; } } } - return 0; - } //-- double getDoubleValue(String, String, XmlPullParser, boolean) + #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; + } /** - * Method getFloatValue. + * 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); + } + + /** + * Method checkFieldWithDuplicate. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return float + * @return boolean */ - 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); - } - } + private boolean checkFieldWithDuplicate(XmlPullParser parser, String tagName, String alias, Set parsed) + throws XmlPullParserException { + if (!(parser.getName().equals(tagName) || parser.getName().equals(alias))) { + return false; } - return 0; - } //-- float getFloatValue(String, String, XmlPullParser, boolean) + if (!parsed.add(tagName)) { + throw new XmlPullParserException("Duplicated tag: '" + tagName + "'", parser, null); + } + return true; + } //-- boolean checkFieldWithDuplicate(XmlPullParser, String, String, Set) /** - * Method getIntegerValue. + * Method checkUnknownAttribute. * - * @param s a s object. * @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. - * @return int + * @throws IOException IOException if any. */ - 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) + 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 getIntegerValue. + * Method checkUnknownElement. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param strict a strict object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return int + * @throws IOException IOException if any. */ - 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); - } + 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--; } } - return defaultValue; - } //-- int getIntegerValue(String, String, XmlPullParser, boolean, int) + } //-- void checkUnknownElement(XmlPullParser, boolean) /** - * Method getLongValue. + * Returns the state of the "add default entities" flag. * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. + * @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, false); + } //-- 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, boolean defaultValue) + throws XmlPullParserException { + if (s != null && s.length() != 0) { + return Boolean.valueOf(s).booleanValue(); + } + return defaultValue; + } //-- 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 @@ -481,294 +771,4 @@ public class ${className} { 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}(XmlNodeBuilder.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 == "*" ) - Map ${field.name} = new LinkedHashMap<>(); - 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); - } - } From be782eec98b6cef0fa456d261ea4cc00962cbb64 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 15 Jun 2023 14:12:11 +0200 Subject: [PATCH 2/6] Fix interpolation --- .../apache/maven/settings/building/DefaultSettingsBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 50710f553b3..c1303ede4d1 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 @@ -208,7 +208,7 @@ private Settings interpolate( return new Settings(new SettingsTransformer(value -> { try { - return interpolator.interpolate(value); + return value != null ? interpolator.interpolate(value) : null; } catch (InterpolationException e) { problems.add( SettingsProblem.Severity.WARNING, From 845fc17ba266438cd2dcd0ca6010f8a275e2ab7f Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 15 Jun 2023 14:42:01 +0200 Subject: [PATCH 3/6] Fix site generation --- maven-settings/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index 8afaee377dc..5856d8feaea 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -54,6 +54,7 @@ under the License. org.codehaus.modello modello-maven-plugin + 2.0.0 ${project.basedir}/../api/maven-api-settings ${project.basedir}/../src/mdo @@ -74,7 +75,6 @@ under the License. generate-sources - 2.0.0 From a01a2bf47f1eaa105394456d534de25945b86df0 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 15 Jun 2023 14:43:59 +0200 Subject: [PATCH 4/6] Remove unused code --- .../building/DefaultSettingsBuilder.java | 46 ------------------- 1 file changed, 46 deletions(-) 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 c1303ede4d1..2c47389b39e 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 @@ -220,51 +220,5 @@ private Settings interpolate( } }) .visit(settings.getDelegate())); - - /* - interpolator.addPostProcessor((expression, value) -> { - if (value != null) { - // we're going to parse this back in as XML so we need to escape XML markup - value = value.toString() - .replace("&", "&") - .replace("<", "<") - .replace(">", ">"); - return value; - } - return null; - }); - - StringWriter writer = new StringWriter(1024 * 4); - - try { - settingsWriter.write(writer, null, settings); - } catch (IOException e) { - throw new IllegalStateException("Failed to serialize settings to memory", e); - } - - String serializedSettings = writer.toString(); - - try { - serializedSettings = interpolator.interpolate(serializedSettings, "settings"); - } catch (InterpolationException e) { - problems.add( - SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1, e); - - return settings; - } - - Settings result; - try { - Map options = Collections.singletonMap(SettingsReader.IS_STRICT, Boolean.FALSE); - result = settingsReader.read(new StringReader(serializedSettings), options); - } catch (IOException e) { - problems.add( - SettingsProblem.Severity.ERROR, "Failed to interpolate settings: " + e.getMessage(), -1, -1, e); - return settings; - } - - return result; - - */ } } From 9a77076c4e15931703188b480ad7ae9238cda133 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 15 Jun 2023 16:16:32 +0200 Subject: [PATCH 5/6] Fix setters in the v3 model --- src/mdo/model-v3.vm | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/mdo/model-v3.vm b/src/mdo/model-v3.vm index afa0d498ada..5508c618f44 100644 --- a/src/mdo/model-v3.vm +++ b/src/mdo/model-v3.vm @@ -183,9 +183,17 @@ public class ${class.name} 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); + if (${field.name} instanceof Xpp3Dom) { + 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 (${field.name} == null) { + if (getDelegate().${pfx}${cap}() != null) { + update(getDelegate().with${cap}(null)); + } + } else { + throw new IllegalArgumentException("Expected an Xpp3Dom object but received: " + ${field.name}); } #elseif( $field.type == "java.util.Properties" ) Map map = ${field.name}.entrySet().stream() @@ -194,7 +202,7 @@ public class ${class.name} update(getDelegate().with${cap}(map)); } #else - if (!Objects.equals(${field.name}, getDelegate().${pfx}${cap}())) { + if (!Objects.equals(${field.name}, ${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()))); From 375db3f6afb92ad75f433bbbcf02ee4f53d9ff99 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 16 Jun 2023 11:08:51 +0200 Subject: [PATCH 6/6] Do not include the locations in the v3 model, fix some docs --- .../maven/api/settings/InputSource.java | 2 +- .../src/main/mdo/settings.mdo | 12 +- maven-settings/pom.xml | 4 +- .../apache/maven/settings/InputLocation.java | 358 ------------------ .../maven/settings/InputLocationTracker.java | 52 --- .../apache/maven/settings/InputSource.java | 99 ----- 6 files changed, 10 insertions(+), 517 deletions(-) delete mode 100644 maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java delete mode 100644 maven-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java delete mode 100644 maven-settings/src/main/java/org/apache/maven/settings/InputSource.java diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java index c87c72a671e..2450c1d7986 100644 --- a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/InputSource.java @@ -32,7 +32,7 @@ public InputSource(String location) { } /** - * Get the path/URL of the POM or {@code null} if unknown. + * Get the path/URL of the settings definition or {@code null} if unknown. * * @return the location */ diff --git a/api/maven-api-settings/src/main/mdo/settings.mdo b/api/maven-api-settings/src/main/mdo/settings.mdo index 07699665b7d..be31553854d 100644 --- a/api/maven-api-settings/src/main/mdo/settings.mdo +++ b/api/maven-api-settings/src/main/mdo/settings.mdo @@ -1083,13 +1083,13 @@ InputLocation - 4.0.0+ + 2.0.0+ - 4.0.0+ + 2.0.0+ InputSource - 4.0.0+ + 2.0.0+ location - 4.0.0+ + 2.0.0+ String - 4.0.0+ + 2.0.0+ packageModelV3=org.apache.maven.settings packageModelV4=org.apache.maven.api.settings packageToolV4=org.apache.maven.settings.v4 - locationTracking=true @@ -83,6 +82,9 @@ under the License. + + locationTracking=true + diff --git a/maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java b/maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java deleted file mode 100644 index 8e7cbae6208..00000000000 --- a/maven-settings/src/main/java/org/apache/maven/settings/InputLocation.java +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.maven.settings; - -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.settings.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.settings.InputLocation toApiLocation() { - if (locations != null && locations.values().contains(this)) { - if (locations.size() == 1 && locations.values().iterator().next() == this) { - return new org.apache.maven.api.settings.InputLocation( - lineNumber, - columnNumber, - source != null ? source.toApiSource() : null, - locations.keySet().iterator().next()); - } else { - return new org.apache.maven.api.settings.InputLocation( - lineNumber, columnNumber, source != null ? source.toApiSource() : null); - } - } else { - return new org.apache.maven.api.settings.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-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java b/maven-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java deleted file mode 100644 index e65408c1491..00000000000 --- a/maven-settings/src/main/java/org/apache/maven/settings/InputLocationTracker.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.maven.settings; - -/** - * 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-settings/src/main/java/org/apache/maven/settings/InputSource.java b/maven-settings/src/main/java/org/apache/maven/settings/InputSource.java deleted file mode 100644 index 0112a8b5074..00000000000 --- a/maven-settings/src/main/java/org/apache/maven/settings/InputSource.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.maven.settings; - -/** - * Class InputSource. - * - * @version $Revision$ $Date$ - */ -@SuppressWarnings("all") -public class InputSource implements java.io.Serializable, Cloneable { - - // --------------------------/ - // - Class/Member Variables -/ - // --------------------------/ - - /** - * - * - * The path/URL of the POM or {@code null} if - * unknown. - * - * - */ - private String location; - - // ----------------/ - // - Constructors -/ - // ----------------/ - - public InputSource() {} - - public InputSource(org.apache.maven.api.settings.InputSource source) { - 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() - - /** - * 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 ) - - @Override - public String toString() { - return getLocation(); - } - - public org.apache.maven.api.settings.InputSource toApiSource() { - return new org.apache.maven.api.settings.InputSource(location); - } -}