mirror of https://github.com/apache/maven.git
[MNG-6656] Introduce base for build/consumer pom
This commit is contained in:
parent
881274914a
commit
bdec668de9
|
@ -60,6 +60,10 @@ under the License.
|
|||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-artifact</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-xml</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-plugin-api</artifactId>
|
||||
|
@ -142,6 +146,11 @@ under the License.
|
|||
<artifactId>hamcrest-library</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -218,6 +227,19 @@ under the License.
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<!-- <phase></phase> -->
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package org.apache.maven.internal.aether;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
import javax.xml.stream.XMLStreamException;
|
||||
import javax.xml.stream.XMLStreamReader;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.sax.SAXTransformerFactory;
|
||||
import javax.xml.transform.sax.TransformerHandler;
|
||||
|
||||
import org.apache.maven.model.building.AbstractModelSourceTransformer;
|
||||
import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.xml.Factories;
|
||||
import org.apache.maven.xml.internal.DefaultConsumerPomXMLFilterFactory;
|
||||
import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
class ConsumerModelSourceTransformer extends AbstractModelSourceTransformer
|
||||
{
|
||||
@Override
|
||||
protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
|
||||
throws TransformerConfigurationException, SAXException, ParserConfigurationException
|
||||
{
|
||||
return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context ) ).get( pomFile );
|
||||
}
|
||||
|
||||
/**
|
||||
* This transformer will ensure that encoding and version are kept.
|
||||
* However, it cannot prevent:
|
||||
* <ul>
|
||||
* <li>attributes will be on one line</li>
|
||||
* <li>Unnecessary whitespace before the rootelement will be removed</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Override
|
||||
protected TransformerHandler getTransformerHandler( Path pomFile )
|
||||
throws IOException, org.apache.maven.model.building.TransformerException
|
||||
{
|
||||
final TransformerHandler transformerHandler;
|
||||
|
||||
final SAXTransformerFactory transformerFactory =
|
||||
(SAXTransformerFactory) Factories.newTransformerFactory();
|
||||
|
||||
// Keep same encoding+version
|
||||
try ( InputStream input = Files.newInputStream( pomFile ) )
|
||||
{
|
||||
XMLStreamReader streamReader =
|
||||
XMLInputFactory.newFactory().createXMLStreamReader( input );
|
||||
|
||||
transformerHandler = transformerFactory.newTransformerHandler();
|
||||
|
||||
final String encoding = streamReader.getCharacterEncodingScheme();
|
||||
final String version = streamReader.getVersion();
|
||||
|
||||
Transformer transformer = transformerHandler.getTransformer();
|
||||
transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
|
||||
if ( encoding == null && version == null )
|
||||
{
|
||||
transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" );
|
||||
}
|
||||
else
|
||||
{
|
||||
transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
|
||||
|
||||
if ( encoding != null )
|
||||
{
|
||||
transformer.setOutputProperty( OutputKeys.ENCODING, encoding );
|
||||
}
|
||||
if ( version != null )
|
||||
{
|
||||
transformer.setOutputProperty( OutputKeys.VERSION, version );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( XMLStreamException | TransformerConfigurationException e )
|
||||
{
|
||||
throw new org.apache.maven.model.building.TransformerException(
|
||||
"Failed to detect XML encoding and version", e );
|
||||
}
|
||||
return transformerHandler;
|
||||
}
|
||||
|
||||
}
|
|
@ -24,6 +24,9 @@ import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
|
|||
import org.apache.maven.bridge.MavenRepositorySystem;
|
||||
import org.apache.maven.eventspy.internal.EventSpyDispatcher;
|
||||
import org.apache.maven.execution.MavenExecutionRequest;
|
||||
import org.apache.maven.feature.Features;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.model.building.TransformerException;
|
||||
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
||||
import org.apache.maven.settings.Mirror;
|
||||
import org.apache.maven.settings.Proxy;
|
||||
|
@ -38,12 +41,16 @@ import org.codehaus.plexus.util.xml.Xpp3Dom;
|
|||
import org.eclipse.aether.ConfigurationProperties;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.SessionData;
|
||||
import org.eclipse.aether.artifact.Artifact;
|
||||
import org.eclipse.aether.repository.LocalRepository;
|
||||
import org.eclipse.aether.repository.NoLocalRepositoryManagerException;
|
||||
import org.eclipse.aether.repository.RepositoryPolicy;
|
||||
import org.eclipse.aether.repository.WorkspaceReader;
|
||||
import org.eclipse.aether.resolution.ResolutionErrorPolicy;
|
||||
import org.eclipse.aether.spi.localrepo.LocalRepositoryManagerFactory;
|
||||
import org.eclipse.aether.transform.FileTransformer;
|
||||
import org.eclipse.aether.transform.TransformException;
|
||||
import org.eclipse.aether.util.repository.AuthenticationBuilder;
|
||||
import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
|
||||
import org.eclipse.aether.util.repository.DefaultMirrorSelector;
|
||||
|
@ -53,8 +60,13 @@ import org.eclipse.sisu.Nullable;
|
|||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -96,7 +108,6 @@ public class DefaultRepositorySystemSessionFactory
|
|||
public DefaultRepositorySystemSession newRepositorySession( MavenExecutionRequest request )
|
||||
{
|
||||
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
|
||||
|
||||
session.setCache( request.getRepositoryCache() );
|
||||
|
||||
Map<Object, Object> configProps = new LinkedHashMap<>();
|
||||
|
@ -139,7 +150,6 @@ public class DefaultRepositorySystemSessionFactory
|
|||
session.setLocalRepositoryManager( simpleLocalRepoMgrFactory.newInstance( session, localRepo ) );
|
||||
logger.info( "Disabling enhanced local repository: using legacy is strongly discouraged to ensure"
|
||||
+ " build reproducibility." );
|
||||
|
||||
}
|
||||
catch ( NoLocalRepositoryManagerException e )
|
||||
{
|
||||
|
@ -238,6 +248,11 @@ public class DefaultRepositorySystemSessionFactory
|
|||
mavenRepositorySystem.injectProxy( session, request.getPluginArtifactRepositories() );
|
||||
mavenRepositorySystem.injectAuthentication( session, request.getPluginArtifactRepositories() );
|
||||
|
||||
if ( Features.buildConsumer().isActive() )
|
||||
{
|
||||
session.setFileTransformerManager( a -> getTransformersForArtifact( a, session.getData() ) );
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
|
@ -266,5 +281,40 @@ public class DefaultRepositorySystemSessionFactory
|
|||
|
||||
return props.getProperty( "version", "unknown-version" );
|
||||
}
|
||||
|
||||
private Collection<FileTransformer> getTransformersForArtifact( final Artifact artifact,
|
||||
final SessionData sessionData )
|
||||
{
|
||||
TransformerContext context = (TransformerContext) sessionData.get( TransformerContext.KEY );
|
||||
Collection<FileTransformer> transformers = new ArrayList<>();
|
||||
|
||||
// In case of install:install-file there's no transformer context, as the goal is unrelated to the lifecycle.
|
||||
if ( "pom".equals( artifact.getExtension() ) && context != null )
|
||||
{
|
||||
transformers.add( new FileTransformer()
|
||||
{
|
||||
@Override
|
||||
public InputStream transformData( File pomFile )
|
||||
throws IOException, TransformException
|
||||
{
|
||||
try
|
||||
{
|
||||
return new ConsumerModelSourceTransformer().transform( pomFile.toPath(), context );
|
||||
}
|
||||
catch ( TransformerException e )
|
||||
{
|
||||
throw new TransformException( e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Artifact transformArtifact( Artifact artifact )
|
||||
{
|
||||
return artifact;
|
||||
}
|
||||
} );
|
||||
}
|
||||
return Collections.unmodifiableCollection( transformers );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ package org.apache.maven.project;
|
|||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
@ -44,6 +45,7 @@ import org.apache.maven.artifact.InvalidRepositoryException;
|
|||
import org.apache.maven.artifact.repository.ArtifactRepository;
|
||||
import org.apache.maven.artifact.repository.LegacyLocalRepositoryManager;
|
||||
import org.apache.maven.bridge.MavenRepositorySystem;
|
||||
import org.apache.maven.feature.Features;
|
||||
import org.apache.maven.model.Build;
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.model.DependencyManagement;
|
||||
|
@ -53,6 +55,7 @@ import org.apache.maven.model.Model;
|
|||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.model.Profile;
|
||||
import org.apache.maven.model.ReportPlugin;
|
||||
import org.apache.maven.model.building.ArtifactModelSource;
|
||||
import org.apache.maven.model.building.DefaultModelBuildingRequest;
|
||||
import org.apache.maven.model.building.DefaultModelProblem;
|
||||
import org.apache.maven.model.building.FileModelSource;
|
||||
|
@ -64,6 +67,7 @@ import org.apache.maven.model.building.ModelProblem;
|
|||
import org.apache.maven.model.building.ModelProcessor;
|
||||
import org.apache.maven.model.building.ModelSource;
|
||||
import org.apache.maven.model.building.StringModelSource;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.model.resolution.ModelResolver;
|
||||
import org.apache.maven.repository.internal.ArtifactDescriptorUtils;
|
||||
import org.codehaus.plexus.logging.Logger;
|
||||
|
@ -291,6 +295,7 @@ public class DefaultProjectBuilder
|
|||
request.setBuildStartTime( configuration.getBuildStartTime() );
|
||||
request.setModelResolver( resolver );
|
||||
request.setModelCache( config.modelCache );
|
||||
request.setTransformerContext( (TransformerContext) config.session.getData().get( TransformerContext.KEY ) );
|
||||
|
||||
return request;
|
||||
}
|
||||
|
@ -342,7 +347,16 @@ public class DefaultProjectBuilder
|
|||
artifact.setResolved( true );
|
||||
}
|
||||
|
||||
return build( localProject ? pomFile : null, new FileModelSource( pomFile ), config );
|
||||
if ( localProject )
|
||||
{
|
||||
return build( pomFile, new FileModelSource( pomFile ), config );
|
||||
}
|
||||
else
|
||||
{
|
||||
return build( null, new ArtifactModelSource( pomFile, artifact.getGroupId(), artifact.getArtifactId(),
|
||||
artifact.getVersion() ),
|
||||
config );
|
||||
}
|
||||
}
|
||||
|
||||
private ModelSource createStubModelSource( Artifact artifact )
|
||||
|
@ -369,7 +383,33 @@ public class DefaultProjectBuilder
|
|||
|
||||
List<InterimResult> interimResults = new ArrayList<>();
|
||||
|
||||
ReactorModelPool modelPool = new ReactorModelPool();
|
||||
ReactorModelPool.Builder poolBuilder = new ReactorModelPool.Builder();
|
||||
final ReactorModelPool modelPool = poolBuilder.build();
|
||||
|
||||
if ( Features.buildConsumer().isActive() )
|
||||
{
|
||||
final TransformerContext context = new TransformerContext()
|
||||
{
|
||||
@Override
|
||||
public String getUserProperty( String key )
|
||||
{
|
||||
return request.getUserProperties().getProperty( key );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getRawModel( Path p )
|
||||
{
|
||||
return modelPool.get( p );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getRawModel( String groupId, String artifactId )
|
||||
{
|
||||
return modelPool.get( groupId, artifactId, null );
|
||||
}
|
||||
};
|
||||
request.getRepositorySession().getData().set( TransformerContext.KEY, context );
|
||||
}
|
||||
|
||||
InternalConfig config = new InternalConfig( request, modelPool,
|
||||
useGlobalModelCache() ? getModelCache() : new ReactorModelCache() );
|
||||
|
@ -378,9 +418,7 @@ public class DefaultProjectBuilder
|
|||
|
||||
boolean noErrors =
|
||||
build( results, interimResults, projectIndex, pomFiles, new LinkedHashSet<>(), true, recursive,
|
||||
config );
|
||||
|
||||
populateReactorModelPool( modelPool, interimResults );
|
||||
config, poolBuilder );
|
||||
|
||||
ClassLoader oldContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
|
@ -406,7 +444,8 @@ public class DefaultProjectBuilder
|
|||
@SuppressWarnings( "checkstyle:parameternumber" )
|
||||
private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults,
|
||||
Map<String, MavenProject> projectIndex, List<File> pomFiles, Set<File> aggregatorFiles,
|
||||
boolean isRoot, boolean recursive, InternalConfig config )
|
||||
boolean root, boolean recursive, InternalConfig config,
|
||||
ReactorModelPool.Builder poolBuilder )
|
||||
{
|
||||
boolean noErrors = true;
|
||||
|
||||
|
@ -414,7 +453,8 @@ public class DefaultProjectBuilder
|
|||
{
|
||||
aggregatorFiles.add( pomFile );
|
||||
|
||||
if ( !build( results, interimResults, projectIndex, pomFile, aggregatorFiles, isRoot, recursive, config ) )
|
||||
if ( !build( results, interimResults, projectIndex, pomFile, aggregatorFiles, root, recursive, config,
|
||||
poolBuilder ) )
|
||||
{
|
||||
noErrors = false;
|
||||
}
|
||||
|
@ -428,7 +468,8 @@ public class DefaultProjectBuilder
|
|||
@SuppressWarnings( "checkstyle:parameternumber" )
|
||||
private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults,
|
||||
Map<String, MavenProject> projectIndex, File pomFile, Set<File> aggregatorFiles,
|
||||
boolean isRoot, boolean recursive, InternalConfig config )
|
||||
boolean isRoot, boolean recursive, InternalConfig config,
|
||||
ReactorModelPool.Builder poolBuilder )
|
||||
{
|
||||
boolean noErrors = true;
|
||||
|
||||
|
@ -465,6 +506,9 @@ public class DefaultProjectBuilder
|
|||
}
|
||||
|
||||
Model model = result.getEffectiveModel();
|
||||
|
||||
poolBuilder.put( model.getPomFile().toPath(), result.getRawModel() );
|
||||
|
||||
try
|
||||
{
|
||||
// first pass: build without building parent.
|
||||
|
@ -559,7 +603,7 @@ public class DefaultProjectBuilder
|
|||
interimResult.modules = new ArrayList<>();
|
||||
|
||||
if ( !build( results, interimResult.modules, projectIndex, moduleFiles, aggregatorFiles, false,
|
||||
recursive, config ) )
|
||||
recursive, config, poolBuilder ) )
|
||||
{
|
||||
noErrors = false;
|
||||
}
|
||||
|
@ -595,17 +639,6 @@ public class DefaultProjectBuilder
|
|||
|
||||
}
|
||||
|
||||
private void populateReactorModelPool( ReactorModelPool reactorModelPool, List<InterimResult> interimResults )
|
||||
{
|
||||
for ( InterimResult interimResult : interimResults )
|
||||
{
|
||||
Model model = interimResult.result.getEffectiveModel();
|
||||
reactorModelPool.put( model.getGroupId(), model.getArtifactId(), model.getVersion(), model.getPomFile() );
|
||||
|
||||
populateReactorModelPool( reactorModelPool, interimResult.modules );
|
||||
}
|
||||
}
|
||||
|
||||
private boolean build( List<ProjectBuildingResult> results, List<MavenProject> projects,
|
||||
Map<String, MavenProject> projectIndex, List<InterimResult> interimResults,
|
||||
ProjectBuildingRequest request, Map<File, Boolean> profilesXmls,
|
||||
|
@ -865,7 +898,7 @@ public class DefaultProjectBuilder
|
|||
DeploymentRepository r = project.getDistributionManagement().getRepository();
|
||||
if ( !StringUtils.isEmpty( r.getId() ) && !StringUtils.isEmpty( r.getUrl() ) )
|
||||
{
|
||||
ArtifactRepository repo = repositorySystem.buildArtifactRepository( r );
|
||||
ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository( r );
|
||||
repositorySystem.injectProxy( projectBuildingRequest.getRepositorySession(),
|
||||
Arrays.asList( repo ) );
|
||||
repositorySystem.injectAuthentication( projectBuildingRequest.getRepositorySession(),
|
||||
|
@ -889,7 +922,7 @@ public class DefaultProjectBuilder
|
|||
DeploymentRepository r = project.getDistributionManagement().getSnapshotRepository();
|
||||
if ( !StringUtils.isEmpty( r.getId() ) && !StringUtils.isEmpty( r.getUrl() ) )
|
||||
{
|
||||
ArtifactRepository repo = repositorySystem.buildArtifactRepository( r );
|
||||
ArtifactRepository repo = MavenRepositorySystem.buildArtifactRepository( r );
|
||||
repositorySystem.injectProxy( projectBuildingRequest.getRepositorySession(),
|
||||
Arrays.asList( repo ) );
|
||||
repositorySystem.injectAuthentication( projectBuildingRequest.getRepositorySession(),
|
||||
|
|
|
@ -19,7 +19,6 @@ package org.apache.maven.project;
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
@ -28,8 +27,10 @@ import java.util.List;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.Parent;
|
||||
import org.apache.maven.model.Repository;
|
||||
import org.apache.maven.model.building.ArtifactModelSource;
|
||||
import org.apache.maven.model.building.FileModelSource;
|
||||
import org.apache.maven.model.building.ModelSource;
|
||||
import org.apache.maven.model.resolution.InvalidRepositoryException;
|
||||
|
@ -155,10 +156,10 @@ public class ProjectModelResolver
|
|||
|
||||
private static void removeMatchingRepository( Iterable<RemoteRepository> repositories, final String id )
|
||||
{
|
||||
Iterator iterator = repositories.iterator( );
|
||||
Iterator<RemoteRepository> iterator = repositories.iterator( );
|
||||
while ( iterator.hasNext() )
|
||||
{
|
||||
RemoteRepository next = ( RemoteRepository ) iterator.next();
|
||||
RemoteRepository next = iterator.next();
|
||||
if ( next.getId().equals( id ) )
|
||||
{
|
||||
iterator.remove();
|
||||
|
@ -174,32 +175,20 @@ public class ProjectModelResolver
|
|||
public ModelSource resolveModel( String groupId, String artifactId, String version )
|
||||
throws UnresolvableModelException
|
||||
{
|
||||
File pomFile = null;
|
||||
Artifact pomArtifact = new DefaultArtifact( groupId, artifactId, "", "pom", version );
|
||||
|
||||
if ( modelPool != null )
|
||||
try
|
||||
{
|
||||
pomFile = modelPool.get( groupId, artifactId, version );
|
||||
ArtifactRequest request = new ArtifactRequest( pomArtifact, repositories, context );
|
||||
request.setTrace( trace );
|
||||
pomArtifact = resolver.resolveArtifact( session, request ).getArtifact();
|
||||
}
|
||||
catch ( ArtifactResolutionException e )
|
||||
{
|
||||
throw new UnresolvableModelException( e.getMessage(), groupId, artifactId, version, e );
|
||||
}
|
||||
|
||||
if ( pomFile == null )
|
||||
{
|
||||
Artifact pomArtifact = new DefaultArtifact( groupId, artifactId, "", "pom", version );
|
||||
|
||||
try
|
||||
{
|
||||
ArtifactRequest request = new ArtifactRequest( pomArtifact, repositories, context );
|
||||
request.setTrace( trace );
|
||||
pomArtifact = resolver.resolveArtifact( session, request ).getArtifact();
|
||||
}
|
||||
catch ( ArtifactResolutionException e )
|
||||
{
|
||||
throw new UnresolvableModelException( e.getMessage(), groupId, artifactId, version, e );
|
||||
}
|
||||
|
||||
pomFile = pomArtifact.getFile();
|
||||
}
|
||||
|
||||
return new FileModelSource( pomFile );
|
||||
return new ArtifactModelSource( pomArtifact.getFile(), groupId, artifactId, version );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -285,6 +274,17 @@ public class ProjectModelResolver
|
|||
}
|
||||
|
||||
dependency.setVersion( versionRangeResult.getHighestVersion().toString() );
|
||||
|
||||
if ( modelPool != null )
|
||||
{
|
||||
Model model =
|
||||
modelPool.get( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() );
|
||||
|
||||
if ( model != null )
|
||||
{
|
||||
return new FileModelSource( model.getPomFile() );
|
||||
}
|
||||
}
|
||||
|
||||
return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() );
|
||||
}
|
||||
|
|
|
@ -19,53 +19,124 @@ package org.apache.maven.project;
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
|
||||
/**
|
||||
* Holds all POM files that are known to the reactor. This allows the project builder to resolve imported POMs from the
|
||||
* Holds all Models that are known to the reactor. This allows the project builder to resolve imported Models from the
|
||||
* reactor when building another project's effective model.
|
||||
*
|
||||
* @author Benjamin Bentmann
|
||||
* @author Robert Scholte
|
||||
*/
|
||||
class ReactorModelPool
|
||||
{
|
||||
private final Map<GAKey, Set<Model>> modelsByGa = new HashMap<>();
|
||||
|
||||
private final Map<CacheKey, File> pomFiles = new HashMap<>();
|
||||
private final Map<Path, Model> modelsByPath = new HashMap<>();
|
||||
|
||||
public File get( String groupId, String artifactId, String version )
|
||||
/**
|
||||
* Get the model by its GAV or (since 3.7.0) by its GA if there is only one.
|
||||
*
|
||||
* @param groupId, never {@code null}
|
||||
* @param artifactId, never {@code null}
|
||||
* @param version, can be {@code null}
|
||||
* @return the matching model or {@code null}
|
||||
* @throws IllegalStateException if version was null and multiple modules share the same groupId + artifactId
|
||||
*/
|
||||
public Model get( String groupId, String artifactId, String version )
|
||||
{
|
||||
return pomFiles.get( new CacheKey( groupId, artifactId, version ) );
|
||||
return modelsByGa.getOrDefault( new GAKey( groupId, artifactId ), Collections.emptySet() ).stream()
|
||||
.filter( m -> version == null || version.equals( getVersion( m ) ) )
|
||||
.reduce( ( a, b ) ->
|
||||
{
|
||||
throw new IllegalStateException( "Multiple modules with key "
|
||||
+ a.getGroupId() + ':' + a.getArtifactId() );
|
||||
} ).orElse( null );
|
||||
}
|
||||
|
||||
public void put( String groupId, String artifactId, String version, File pomFile )
|
||||
/**
|
||||
* Find model by path, useful when location the parent by relativePath
|
||||
*
|
||||
* @param path
|
||||
* @return the matching model or {@code null}
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public Model get( Path path )
|
||||
{
|
||||
pomFiles.put( new CacheKey( groupId, artifactId, version ), pomFile );
|
||||
final Path pomFile;
|
||||
if ( Files.isDirectory( path ) )
|
||||
{
|
||||
pomFile = path.resolve( "pom.xml" );
|
||||
}
|
||||
else
|
||||
{
|
||||
pomFile = path;
|
||||
}
|
||||
return modelsByPath.get( pomFile );
|
||||
}
|
||||
|
||||
private String getVersion( Model model )
|
||||
{
|
||||
String version = model.getVersion();
|
||||
if ( version == null && model.getParent() != null )
|
||||
{
|
||||
version = model.getParent().getVersion();
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
private static final class CacheKey
|
||||
static class Builder
|
||||
{
|
||||
private ReactorModelPool pool = new ReactorModelPool();
|
||||
|
||||
Builder put( Path pomFile, Model model )
|
||||
{
|
||||
pool.modelsByPath.put( pomFile, model );
|
||||
pool.modelsByGa.computeIfAbsent( new GAKey( getGroupId( model ), model.getArtifactId() ),
|
||||
k -> new HashSet<Model>() ).add( model );
|
||||
return this;
|
||||
}
|
||||
|
||||
ReactorModelPool build()
|
||||
{
|
||||
return pool;
|
||||
}
|
||||
|
||||
private static String getGroupId( Model model )
|
||||
{
|
||||
String groupId = model.getGroupId();
|
||||
if ( groupId == null && model.getParent() != null )
|
||||
{
|
||||
groupId = model.getParent().getGroupId();
|
||||
}
|
||||
return groupId;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class GAKey
|
||||
{
|
||||
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
|
||||
private final String version;
|
||||
|
||||
private final int hashCode;
|
||||
|
||||
CacheKey( String groupId, String artifactId, String version )
|
||||
GAKey( String groupId, String artifactId )
|
||||
{
|
||||
this.groupId = ( groupId != null ) ? groupId : "";
|
||||
this.artifactId = ( artifactId != null ) ? artifactId : "";
|
||||
this.version = ( version != null ) ? version : "";
|
||||
|
||||
int hash = 17;
|
||||
hash = hash * 31 + this.groupId.hashCode();
|
||||
hash = hash * 31 + this.artifactId.hashCode();
|
||||
hash = hash * 31 + this.version.hashCode();
|
||||
hashCode = hash;
|
||||
hashCode = Objects.hash( this.groupId, this.artifactId );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,15 +147,9 @@ class ReactorModelPool
|
|||
return true;
|
||||
}
|
||||
|
||||
if ( !( obj instanceof CacheKey ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
GAKey that = (GAKey) obj;
|
||||
|
||||
CacheKey that = (CacheKey) obj;
|
||||
|
||||
return artifactId.equals( that.artifactId ) && groupId.equals( that.groupId )
|
||||
&& version.equals( that.version );
|
||||
return artifactId.equals( that.artifactId ) && groupId.equals( that.groupId );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -97,10 +162,9 @@ class ReactorModelPool
|
|||
public String toString()
|
||||
{
|
||||
StringBuilder buffer = new StringBuilder( 128 );
|
||||
buffer.append( groupId ).append( ':' ).append( artifactId ).append( ':' ).append( version );
|
||||
buffer.append( groupId ).append( ':' ).append( artifactId );
|
||||
return buffer.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
package org.apache.maven.xml.internal;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.xml.sax.filter.ConsumerPomXMLFilterFactory;
|
||||
|
||||
/**
|
||||
* The default implementation of the {@link ConsumerPomXMLFilterFactory}
|
||||
* It will provide several values for the consumer pom based on its context.
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class DefaultConsumerPomXMLFilterFactory extends ConsumerPomXMLFilterFactory
|
||||
{
|
||||
private final TransformerContext context;
|
||||
|
||||
public DefaultConsumerPomXMLFilterFactory( DefaultBuildPomXMLFilterFactory buildPomXMLFilterFactory )
|
||||
{
|
||||
super( buildPomXMLFilterFactory );
|
||||
this.context = buildPomXMLFilterFactory.getContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> getChangelist()
|
||||
{
|
||||
return Optional.ofNullable( context.getUserProperty( "changelist" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> getRevision()
|
||||
{
|
||||
return Optional.ofNullable( context.getUserProperty( "revision" ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> getSha1()
|
||||
{
|
||||
return Optional.ofNullable( context.getUserProperty( "sha1" ) );
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -159,7 +159,7 @@ public class ProjectBuilderTest
|
|||
File parent = new File( tempDir.toFile(), "pom.xml" );
|
||||
String parentContent = FileUtils.fileRead( parent );
|
||||
parentContent = parentContent.replaceAll( "<packaging>pom</packaging>",
|
||||
"<packaging>pom</packaging><properties><addedProperty>addedValue</addedProperty></properties>" );
|
||||
"<packaging>pom</packaging><properties><addedProperty>addedValue</addedProperty></properties>" );
|
||||
FileUtils.fileWrite( parent, "UTF-8", parentContent );
|
||||
// re-build pom with modified parent
|
||||
ProjectBuildingResult result = projectBuilder.build( child, configuration );
|
||||
|
|
|
@ -111,14 +111,14 @@ public class TestRepositorySystem
|
|||
public ArtifactRepository createDefaultLocalRepository()
|
||||
throws InvalidRepositoryException
|
||||
{
|
||||
return createLocalRepository( new File( System.getProperty( "basedir", "" ), "target/local-repo" ).getAbsoluteFile() );
|
||||
return createLocalRepository( new File( System.getProperty( "basedir", "." ), "target/local-repo" ).getAbsoluteFile() );
|
||||
}
|
||||
|
||||
public ArtifactRepository createDefaultRemoteRepository()
|
||||
throws InvalidRepositoryException
|
||||
{
|
||||
return new MavenArtifactRepository( DEFAULT_REMOTE_REPO_ID, "file://"
|
||||
+ new File( System.getProperty( "basedir", "" ), "src/test/remote-repo" ).toURI().getPath(),
|
||||
+ new File( System.getProperty( "basedir", "." ), "src/test/remote-repo" ).getAbsoluteFile().toURI().getPath(),
|
||||
new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(),
|
||||
new ArtifactRepositoryPolicy() );
|
||||
}
|
||||
|
|
|
@ -58,6 +58,11 @@ under the License.
|
|||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-builder-support</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-xml</artifactId>
|
||||
</dependency>
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.sisu</groupId>
|
||||
<artifactId>org.eclipse.sisu.inject</artifactId>
|
||||
|
@ -67,7 +72,6 @@ under the License.
|
|||
<artifactId>org.eclipse.sisu.plexus</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>com.google.inject</groupId>
|
||||
<artifactId>guice</artifactId>
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package org.apache.maven.feature;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Centralized class for feature information
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public final class Features
|
||||
{
|
||||
private Features()
|
||||
{
|
||||
}
|
||||
|
||||
private static final Feature BUILDCONSUMER = new Feature( "maven.experimental.buildconsumer", "true" );
|
||||
|
||||
public static Feature buildConsumer()
|
||||
{
|
||||
return BUILDCONSUMER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents some feature
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public static class Feature
|
||||
{
|
||||
private final boolean active;
|
||||
|
||||
Feature( String name, String defaultValue )
|
||||
{
|
||||
active = "true".equals( System.getProperty( name, defaultValue ) );
|
||||
}
|
||||
|
||||
public boolean isActive()
|
||||
{
|
||||
return active;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,199 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PipedInputStream;
|
||||
import java.io.PipedOutputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.sax.TransformerHandler;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.maven.xml.Factories;
|
||||
import org.apache.maven.xml.sax.ext.CommentRenormalizer;
|
||||
import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Offers a transformation implementation based on PipelineStreams.
|
||||
* Subclasses are responsible for providing the right SAXFilter.
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public abstract class AbstractModelSourceTransformer
|
||||
implements ModelSourceTransformer
|
||||
{
|
||||
private static final AtomicInteger TRANSFORM_THREAD_COUNTER = new AtomicInteger();
|
||||
|
||||
private final TransformerFactory transformerFactory = Factories.newTransformerFactory();
|
||||
|
||||
protected abstract AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
|
||||
throws TransformerConfigurationException, SAXException, ParserConfigurationException;
|
||||
|
||||
protected OutputStream filterOutputStream( OutputStream outputStream, Path pomFile )
|
||||
{
|
||||
return outputStream;
|
||||
}
|
||||
|
||||
protected TransformerHandler getTransformerHandler( Path pomFile )
|
||||
throws IOException, org.apache.maven.model.building.TransformerException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final InputStream transform( Path pomFile, TransformerContext context )
|
||||
throws IOException, org.apache.maven.model.building.TransformerException
|
||||
{
|
||||
final TransformerHandler transformerHandler = getTransformerHandler( pomFile );
|
||||
|
||||
final AbstractSAXFilter filter;
|
||||
try
|
||||
{
|
||||
filter = getSAXFilter( pomFile, context );
|
||||
filter.setLexicalHandler( transformerHandler );
|
||||
}
|
||||
catch ( TransformerConfigurationException | SAXException | ParserConfigurationException e )
|
||||
{
|
||||
throw new org.apache.maven.model.building.TransformerException( e );
|
||||
}
|
||||
|
||||
final SAXSource transformSource =
|
||||
new SAXSource( filter,
|
||||
new org.xml.sax.InputSource( new FileInputStream( pomFile.toFile() ) ) );
|
||||
|
||||
final PipedOutputStream pout = new PipedOutputStream();
|
||||
final PipedInputStream pipedInputStream = new PipedInputStream( pout );
|
||||
|
||||
OutputStream out = filterOutputStream( pout, pomFile );
|
||||
|
||||
final javax.xml.transform.Result result;
|
||||
if ( transformerHandler == null )
|
||||
{
|
||||
result = new StreamResult( out );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = new SAXResult( transformerHandler );
|
||||
( (SAXResult) result ).setLexicalHandler( new CommentRenormalizer( transformerHandler ) );
|
||||
transformerHandler.setResult( new StreamResult( out ) );
|
||||
}
|
||||
|
||||
IOExceptionHandler eh = new IOExceptionHandler();
|
||||
|
||||
Thread transformThread = new Thread( () ->
|
||||
{
|
||||
try ( PipedOutputStream pos = pout )
|
||||
{
|
||||
transformerFactory.newTransformer().transform( transformSource, result );
|
||||
}
|
||||
catch ( TransformerException | IOException e )
|
||||
{
|
||||
eh.uncaughtException( Thread.currentThread(), e );
|
||||
}
|
||||
}, "TransformThread-" + TRANSFORM_THREAD_COUNTER.incrementAndGet() );
|
||||
transformThread.setUncaughtExceptionHandler( eh );
|
||||
transformThread.setDaemon( true );
|
||||
transformThread.start();
|
||||
|
||||
return new ThreadAwareInputStream( pipedInputStream, eh );
|
||||
}
|
||||
|
||||
private static class IOExceptionHandler
|
||||
implements Thread.UncaughtExceptionHandler, AutoCloseable
|
||||
{
|
||||
private volatile Throwable cause;
|
||||
|
||||
@Override
|
||||
public void uncaughtException( Thread t, Throwable e )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch ( TransformerException | IOException | RuntimeException | Error allGood )
|
||||
{
|
||||
// all good
|
||||
this.cause = e;
|
||||
}
|
||||
catch ( Throwable notGood )
|
||||
{
|
||||
throw new AssertionError( "Unexpected Exception", e );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
if ( cause != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
throw cause;
|
||||
}
|
||||
catch ( IOException | RuntimeException | Error e )
|
||||
{
|
||||
throw e;
|
||||
}
|
||||
catch ( Throwable t )
|
||||
{
|
||||
// Any checked exception
|
||||
throw new RuntimeException( "Failed to transform pom", t );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ThreadAwareInputStream
|
||||
extends FilterInputStream
|
||||
{
|
||||
final IOExceptionHandler h;
|
||||
|
||||
protected ThreadAwareInputStream( InputStream in, IOExceptionHandler h )
|
||||
{
|
||||
super( in );
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
throws IOException
|
||||
{
|
||||
try ( IOExceptionHandler eh = h )
|
||||
{
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
|
||||
import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
|
||||
import org.apache.maven.xml.sax.filter.BuildPomXMLFilterFactory;
|
||||
import org.apache.maven.xml.sax.filter.BuildPomXMLFilterListener;
|
||||
import org.eclipse.sisu.Nullable;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* ModelSourceTransformer for the build pom
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
@Named
|
||||
@Singleton
|
||||
class BuildModelSourceTransformer extends AbstractModelSourceTransformer
|
||||
{
|
||||
@Inject
|
||||
@Nullable
|
||||
private BuildPomXMLFilterListener xmlFilterListener;
|
||||
|
||||
protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
|
||||
throws TransformerConfigurationException, SAXException, ParserConfigurationException
|
||||
{
|
||||
BuildPomXMLFilterFactory buildPomXMLFilterFactory = new DefaultBuildPomXMLFilterFactory( context );
|
||||
|
||||
return buildPomXMLFilterFactory.get( pomFile );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected OutputStream filterOutputStream( OutputStream outputStream, Path pomFile )
|
||||
{
|
||||
OutputStream out;
|
||||
if ( xmlFilterListener != null )
|
||||
{
|
||||
out = new FilterOutputStream( outputStream )
|
||||
{
|
||||
@Override
|
||||
public void write( byte[] b, int off, int len )
|
||||
throws IOException
|
||||
{
|
||||
super.write( b, off, len );
|
||||
xmlFilterListener.write( pomFile, b, off, len );
|
||||
}
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
out = outputStream;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.xml.sax.filter.BuildPomXMLFilterFactory;
|
||||
import org.apache.maven.xml.sax.filter.RelativeProject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class DefaultBuildPomXMLFilterFactory extends BuildPomXMLFilterFactory
|
||||
{
|
||||
private final TransformerContext context;
|
||||
|
||||
public DefaultBuildPomXMLFilterFactory( TransformerContext context )
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public final TransformerContext getContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Function<Path, Optional<RelativeProject>> getRelativePathMapper()
|
||||
{
|
||||
return p -> Optional.ofNullable( context.getRawModel( p ) ).map( m -> toRelativeProject( m ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BiFunction<String, String, String> getDependencyKeyToVersionMapper()
|
||||
{
|
||||
return (g, a) -> Optional.ofNullable( context.getRawModel( g, a ) )
|
||||
.map( m -> toVersion( m ) )
|
||||
.orElse( null );
|
||||
}
|
||||
|
||||
private static RelativeProject toRelativeProject( final Model m )
|
||||
{
|
||||
String groupId = m.getGroupId();
|
||||
if ( groupId == null && m.getParent() != null )
|
||||
{
|
||||
groupId = m.getParent().getGroupId();
|
||||
}
|
||||
|
||||
String version = m.getVersion();
|
||||
if ( version == null && m.getParent() != null )
|
||||
{
|
||||
version = m.getParent().getVersion();
|
||||
}
|
||||
|
||||
return new RelativeProject( groupId, m.getArtifactId(), version );
|
||||
}
|
||||
|
||||
private static String toVersion( final Model m )
|
||||
{
|
||||
String version = m.getVersion();
|
||||
if ( version == null && m.getParent() != null )
|
||||
{
|
||||
version = m.getParent().getVersion();
|
||||
}
|
||||
|
||||
return version;
|
||||
}
|
||||
}
|
|
@ -19,22 +19,49 @@ package org.apache.maven.model.building;
|
|||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.apache.maven.model.building.Result.error;
|
||||
import static org.apache.maven.model.building.Result.newResult;
|
||||
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
|
||||
import org.apache.maven.artifact.versioning.VersionRange;
|
||||
import org.apache.maven.building.Source;
|
||||
import org.apache.maven.feature.Features;
|
||||
import org.apache.maven.model.Activation;
|
||||
import org.apache.maven.model.Build;
|
||||
import org.apache.maven.model.BuildBase;
|
||||
import org.apache.maven.model.CiManagement;
|
||||
import org.apache.maven.model.Dependency;
|
||||
import org.apache.maven.model.DependencyManagement;
|
||||
import org.apache.maven.model.InputLocation;
|
||||
import org.apache.maven.model.InputSource;
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.ModelBase;
|
||||
import org.apache.maven.model.Parent;
|
||||
import org.apache.maven.model.Plugin;
|
||||
import org.apache.maven.model.PluginContainer;
|
||||
import org.apache.maven.model.PluginManagement;
|
||||
import org.apache.maven.model.Profile;
|
||||
import org.apache.maven.model.ReportPlugin;
|
||||
import org.apache.maven.model.Reporting;
|
||||
import org.apache.maven.model.Repository;
|
||||
import org.apache.maven.model.building.ModelProblem.Severity;
|
||||
import org.apache.maven.model.building.ModelProblem.Version;
|
||||
|
@ -44,6 +71,7 @@ import org.apache.maven.model.interpolation.ModelInterpolator;
|
|||
import org.apache.maven.model.io.ModelParseException;
|
||||
import org.apache.maven.model.management.DependencyManagementInjector;
|
||||
import org.apache.maven.model.management.PluginManagementInjector;
|
||||
import org.apache.maven.model.merge.ModelMerger;
|
||||
import org.apache.maven.model.normalization.ModelNormalizer;
|
||||
import org.apache.maven.model.path.ModelPathTranslator;
|
||||
import org.apache.maven.model.path.ModelUrlNormalizer;
|
||||
|
@ -64,25 +92,6 @@ import org.codehaus.plexus.interpolation.MapBasedValueSource;
|
|||
import org.codehaus.plexus.interpolation.StringSearchInterpolator;
|
||||
import org.eclipse.sisu.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import static org.apache.maven.model.building.Result.error;
|
||||
import static org.apache.maven.model.building.Result.newResult;
|
||||
|
||||
/**
|
||||
* @author Benjamin Bentmann
|
||||
*/
|
||||
|
@ -108,7 +117,7 @@ public class DefaultModelBuilder
|
|||
|
||||
@Inject
|
||||
private ModelUrlNormalizer modelUrlNormalizer;
|
||||
|
||||
|
||||
@Inject
|
||||
private SuperPomProvider superPomProvider;
|
||||
|
||||
|
@ -142,6 +151,8 @@ public class DefaultModelBuilder
|
|||
|
||||
@Inject
|
||||
private ReportingConverter reportingConverter;
|
||||
|
||||
private ModelMerger modelMerger = new FileToRawModelMerger();
|
||||
|
||||
public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor )
|
||||
{
|
||||
|
@ -244,7 +255,7 @@ public class DefaultModelBuilder
|
|||
this.reportingConverter = reportingConverter;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings( "checkstyle:methodlength" )
|
||||
@Override
|
||||
public ModelBuildingResult build( ModelBuildingRequest request )
|
||||
|
@ -426,7 +437,7 @@ public class DefaultModelBuilder
|
|||
}
|
||||
|
||||
result.setEffectiveModel( resultModel );
|
||||
|
||||
|
||||
for ( ModelData currentData : lineage )
|
||||
{
|
||||
String modelId = ( currentData != superData ) ? currentData.getId() : "";
|
||||
|
@ -529,6 +540,7 @@ public class DefaultModelBuilder
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings( "checkstyle:methodlength" )
|
||||
private Model readModel( ModelSource modelSource, File pomFile, ModelBuildingRequest request,
|
||||
DefaultModelProblemCollector problems )
|
||||
throws ModelBuildingException
|
||||
|
@ -637,7 +649,6 @@ public class DefaultModelBuilder
|
|||
.setMessage( "Non-readable POM " + modelSource.getLocation() + ": " + msg ).setException( e ) );
|
||||
throw problems.newModelBuildingException();
|
||||
}
|
||||
|
||||
if ( pomFile != null )
|
||||
{
|
||||
model.setPomFile( pomFile );
|
||||
|
@ -646,8 +657,33 @@ public class DefaultModelBuilder
|
|||
{
|
||||
model.setPomFile( ( (FileModelSource) modelSource ).getFile() );
|
||||
}
|
||||
|
||||
problems.setSource( model );
|
||||
|
||||
modelValidator.validateFileModel( model, request, problems );
|
||||
request.setFileModel( model );
|
||||
|
||||
if ( Features.buildConsumer().isActive() && pomFile != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
Model rawModel =
|
||||
modelProcessor.read( pomFile,
|
||||
Collections.singletonMap( "transformerContext", request.getTransformerContext() ) );
|
||||
|
||||
model.setPomFile( pomFile );
|
||||
|
||||
// model with locationTrackers, required for proper feedback during validations
|
||||
model = request.getFileModel().clone();
|
||||
|
||||
// Apply enriched data
|
||||
modelMerger.merge( model, rawModel, false, null );
|
||||
}
|
||||
catch ( IOException e )
|
||||
{
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.V37 ).setException( e ) );
|
||||
}
|
||||
}
|
||||
|
||||
modelValidator.validateRawModel( model, request, problems );
|
||||
|
||||
if ( hasFatalErrors( problems ) )
|
||||
|
@ -953,12 +989,17 @@ public class DefaultModelBuilder
|
|||
|
||||
if ( parentData == null )
|
||||
{
|
||||
parentData = fromCache( request.getModelCache(),
|
||||
parent.getGroupId(), parent.getArtifactId(),
|
||||
parent.getVersion(), ModelCacheTag.RAW );
|
||||
ModelData candidateData = fromCache( request.getModelCache(),
|
||||
parent.getGroupId(), parent.getArtifactId(),
|
||||
parent.getVersion(), ModelCacheTag.RAW );
|
||||
|
||||
|
||||
// ArtifactModelSource means repositorySource
|
||||
if ( parentData == null || !( parentData.getSource() instanceof ArtifactModelSource ) )
|
||||
if ( candidateData != null && candidateData.getSource() instanceof ArtifactModelSource )
|
||||
{
|
||||
// ArtifactModelSource means repositorySource
|
||||
parentData = candidateData;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentData = readParentExternally( childModel, request, problems );
|
||||
|
||||
|
@ -967,21 +1008,20 @@ public class DefaultModelBuilder
|
|||
parentData.getVersion(), ModelCacheTag.RAW, parentData );
|
||||
}
|
||||
}
|
||||
|
||||
Model parentModel = parentData.getModel();
|
||||
|
||||
if ( !"pom".equals( parentModel.getPackaging() ) )
|
||||
|
||||
if ( parentData != null )
|
||||
{
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
|
||||
.setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
|
||||
+ ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
|
||||
.setLocation( parentModel.getLocation( "packaging" ) ) );
|
||||
Model parentModel = parentData.getModel();
|
||||
|
||||
if ( !"pom".equals( parentModel.getPackaging() ) )
|
||||
{
|
||||
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE )
|
||||
.setMessage( "Invalid packaging for parent POM " + ModelProblemUtils.toSourceHint( parentModel )
|
||||
+ ", must be \"pom\" but is \"" + parentModel.getPackaging() + "\"" )
|
||||
.setLocation( parentModel.getLocation( "packaging" ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parentData = null;
|
||||
}
|
||||
|
||||
return parentData;
|
||||
}
|
||||
|
@ -1353,7 +1393,7 @@ public class DefaultModelBuilder
|
|||
final ModelSource importSource;
|
||||
try
|
||||
{
|
||||
importSource = modelResolver.resolveModel( groupId, artifactId, version );
|
||||
importSource = modelResolver.resolveModel( dependency );
|
||||
}
|
||||
catch ( UnresolvableModelException e )
|
||||
{
|
||||
|
@ -1516,4 +1556,155 @@ public class DefaultModelBuilder
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* As long as Maven controls the BuildPomXMLFilter, the entities that need merging are known.
|
||||
* All others can simply be copied from source to target to restore the locationTracker
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class FileToRawModelMerger extends ModelMerger
|
||||
{
|
||||
@Override
|
||||
protected void mergeBuild_Extensions( Build target, Build source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeCiManagement_Notifiers( CiManagement target, CiManagement source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source,
|
||||
boolean sourceDominant, Map<Object, Object> context )
|
||||
{
|
||||
Iterator<Dependency> sourceIterator = source.getDependencies().iterator();
|
||||
target.getDependencies().stream().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant,
|
||||
context ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
Iterator<Profile> sourceIterator = source.getProfiles().iterator();
|
||||
target.getProfiles().stream().forEach( t -> mergeProfile( t, sourceIterator.next(), sourceDominant,
|
||||
context ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
Iterator<Dependency> sourceIterator = source.getDependencies().iterator();
|
||||
target.getDependencies().stream().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant,
|
||||
context ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
target.setPluginRepositories( source.getPluginRepositories() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
Iterator<Dependency> sourceIterator = source.getDependencies().iterator();
|
||||
target.getDependencies().stream().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant,
|
||||
context ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant,
|
||||
Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source,
|
||||
boolean sourceDominant, Map<Object, Object> context )
|
||||
{
|
||||
// don't merge
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,9 @@ public class DefaultModelBuilderFactory
|
|||
|
||||
protected ModelReader newModelReader()
|
||||
{
|
||||
return new DefaultModelReader();
|
||||
DefaultModelReader reader = new DefaultModelReader();
|
||||
reader.setTransformer( newModelSourceTransformer() );
|
||||
return reader;
|
||||
}
|
||||
|
||||
protected ProfileSelector newProfileSelector()
|
||||
|
@ -199,6 +201,11 @@ public class DefaultModelBuilderFactory
|
|||
return new DefaultReportingConverter();
|
||||
}
|
||||
|
||||
private ModelSourceTransformer newModelSourceTransformer()
|
||||
{
|
||||
return new DefaultModelSourceTransformer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new model builder instance.
|
||||
*
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.apache.maven.model.resolution.WorkspaceModelResolver;
|
|||
public class DefaultModelBuildingRequest
|
||||
implements ModelBuildingRequest
|
||||
{
|
||||
private Model fileModel;
|
||||
|
||||
private Model rawModel;
|
||||
|
||||
|
@ -72,6 +73,8 @@ public class DefaultModelBuildingRequest
|
|||
private ModelCache modelCache;
|
||||
|
||||
private WorkspaceModelResolver workspaceResolver;
|
||||
|
||||
private TransformerContext context;
|
||||
|
||||
/**
|
||||
* Creates an empty request.
|
||||
|
@ -382,6 +385,19 @@ public class DefaultModelBuildingRequest
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getFileModel()
|
||||
{
|
||||
return fileModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setFileModel( Model fileModel )
|
||||
{
|
||||
this.fileModel = fileModel;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getRawModel()
|
||||
{
|
||||
|
@ -407,5 +423,17 @@ public class DefaultModelBuildingRequest
|
|||
this.workspaceResolver = workspaceResolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TransformerContext getTransformerContext()
|
||||
{
|
||||
return context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setTransformerContext( TransformerContext context )
|
||||
{
|
||||
this.context = context;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Default ModelSourceTransformer, provides pomFile as inputStream and ignores the context
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class DefaultModelSourceTransformer implements ModelSourceTransformer
|
||||
{
|
||||
|
||||
@Override
|
||||
public InputStream transform( Path pomFile, TransformerContext context )
|
||||
throws IOException, TransformerException
|
||||
{
|
||||
return Files.newInputStream( pomFile );
|
||||
}
|
||||
|
||||
}
|
|
@ -256,6 +256,19 @@ class FilterModelBuildingRequest
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getFileModel()
|
||||
{
|
||||
return request.getFileModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setFileModel( Model fileModel )
|
||||
{
|
||||
request.setFileModel( fileModel );
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model getRawModel()
|
||||
{
|
||||
|
@ -281,5 +294,17 @@ class FilterModelBuildingRequest
|
|||
request.setWorkspaceModelResolver( workspaceResolver );
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TransformerContext getTransformerContext()
|
||||
{
|
||||
return request.getTransformerContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelBuildingRequest setTransformerContext( TransformerContext context )
|
||||
{
|
||||
request.setTransformerContext( context );
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -63,6 +63,21 @@ public interface ModelBuildingRequest
|
|||
* Denotes strict validation as recommended by the current Maven version.
|
||||
*/
|
||||
int VALIDATION_LEVEL_STRICT = VALIDATION_LEVEL_MAVEN_3_0;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the file model
|
||||
* @since 3.7.0
|
||||
*/
|
||||
Model getFileModel();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param fileModel
|
||||
* @return This request, never {@code null}.
|
||||
* @since 3.7.0
|
||||
*/
|
||||
ModelBuildingRequest setFileModel( Model fileModel );
|
||||
|
||||
/**
|
||||
* Gets the raw model to build. If not set, model source will be used to load raw model.
|
||||
|
@ -334,5 +349,10 @@ public interface ModelBuildingRequest
|
|||
WorkspaceModelResolver getWorkspaceModelResolver();
|
||||
|
||||
ModelBuildingRequest setWorkspaceModelResolver( WorkspaceModelResolver workspaceResolver );
|
||||
|
||||
TransformerContext getTransformerContext();
|
||||
|
||||
ModelBuildingRequest setTransformerContext( TransformerContext context );
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -50,7 +50,8 @@ public interface ModelProblem
|
|||
BASE,
|
||||
V20,
|
||||
V30,
|
||||
V31
|
||||
V31,
|
||||
V37
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public interface ModelSourceTransformer
|
||||
{
|
||||
InputStream transform( Path pomFile, TransformerContext context )
|
||||
throws IOException, TransformerException;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
|
||||
/**
|
||||
* Context used to transform a pom file.
|
||||
*
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public interface TransformerContext
|
||||
{
|
||||
/**
|
||||
* Key to get the TransformerContext from the SessionData
|
||||
*/
|
||||
Object KEY = TransformerContext.class;
|
||||
|
||||
/**
|
||||
* Get the value of the commandline argument {@code -Dkey=value}
|
||||
* @param key
|
||||
* @return
|
||||
*/
|
||||
String getUserProperty( String key );
|
||||
|
||||
/**
|
||||
* Get the model based on the path, will be used to resolve the parent based on relativePath
|
||||
*
|
||||
* @param p the path
|
||||
* @return the model, otherwise {@code null}
|
||||
*/
|
||||
Model getRawModel( Path p );
|
||||
|
||||
/**
|
||||
* Get the model from the reactor based on the groupId and artifactId, will be used for reactor dependencies
|
||||
*
|
||||
* @param groupId the groupId
|
||||
* @param artifactId the artifactId
|
||||
* @return the model, otherwise {@code null}
|
||||
* @throws IllegalStateException if multiple versions of the same GA are part of the reactor
|
||||
*/
|
||||
Model getRawModel( String groupId, String artifactId ) throws IllegalStateException;
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class TransformerException extends Exception
|
||||
{
|
||||
|
||||
public TransformerException( Exception e )
|
||||
{
|
||||
super ( e );
|
||||
}
|
||||
|
||||
public TransformerException( String message, Throwable exception )
|
||||
{
|
||||
super( message, exception );
|
||||
}
|
||||
|
||||
}
|
|
@ -27,11 +27,15 @@ import java.io.Reader;
|
|||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.apache.maven.model.InputSource;
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.building.ModelSourceTransformer;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.model.building.TransformerException;
|
||||
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
|
||||
import org.apache.maven.model.io.xpp3.MavenXpp3ReaderEx;
|
||||
import org.codehaus.plexus.util.ReaderFactory;
|
||||
|
@ -48,18 +52,51 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
|
|||
public class DefaultModelReader
|
||||
implements ModelReader
|
||||
{
|
||||
@Inject
|
||||
private ModelSourceTransformer transformer;
|
||||
|
||||
public void setTransformer( ModelSourceTransformer transformer )
|
||||
{
|
||||
this.transformer = transformer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Model read( File input, Map<String, ?> options )
|
||||
throws IOException
|
||||
{
|
||||
Objects.requireNonNull( input, "input cannot be null" );
|
||||
|
||||
Model model = read( new FileInputStream( input ), options );
|
||||
TransformerContext context = null;
|
||||
if ( options != null )
|
||||
{
|
||||
context = (TransformerContext) options.get( "transformerContext" );
|
||||
}
|
||||
|
||||
model.setPomFile( input );
|
||||
final InputStream is;
|
||||
if ( context == null )
|
||||
{
|
||||
is = new FileInputStream( input );
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
is = transformer.transform( input.toPath(), context );
|
||||
}
|
||||
catch ( TransformerException e )
|
||||
{
|
||||
throw new IOException( "Failed to transform " + input, e );
|
||||
}
|
||||
}
|
||||
|
||||
return model;
|
||||
try ( InputStream in = is )
|
||||
{
|
||||
Model model = read( is, options );
|
||||
|
||||
model.setPomFile( input );
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -88,7 +88,7 @@ public class DefaultModelValidator
|
|||
private final Set<String> validIds = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void validateRawModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems )
|
||||
public void validateFileModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems )
|
||||
{
|
||||
Parent parent = m.getParent();
|
||||
if ( parent != null )
|
||||
|
@ -99,9 +99,6 @@ public class DefaultModelValidator
|
|||
validateStringNotEmpty( "parent.artifactId", problems, Severity.FATAL, Version.BASE, parent.getArtifactId(),
|
||||
parent );
|
||||
|
||||
validateStringNotEmpty( "parent.version", problems, Severity.FATAL, Version.BASE, parent.getVersion(),
|
||||
parent );
|
||||
|
||||
if ( equals( parent.getGroupId(), m.getGroupId() ) && equals( parent.getArtifactId(), m.getArtifactId() ) )
|
||||
{
|
||||
addViolation( problems, Severity.FATAL, Version.BASE, "parent.artifactId", null,
|
||||
|
@ -120,6 +117,17 @@ public class DefaultModelValidator
|
|||
|
||||
if ( request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
|
||||
{
|
||||
Set<String> modules = new HashSet<>();
|
||||
for ( int i = 0, n = m.getModules().size(); i < n; i++ )
|
||||
{
|
||||
String module = m.getModules().get( i );
|
||||
if ( !modules.add( module ) )
|
||||
{
|
||||
addViolation( problems, Severity.ERROR, Version.V20, "modules.module[" + i + "]", null,
|
||||
"specifies duplicate child module " + module, m.getLocation( "modules" ) );
|
||||
}
|
||||
}
|
||||
|
||||
Severity errOn30 = getSeverity( request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0 );
|
||||
|
||||
// [MNG-6074] Maven should produce an error if no model version has been set in a POM file used to build an
|
||||
|
@ -221,6 +229,18 @@ public class DefaultModelValidator
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validateRawModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems )
|
||||
{
|
||||
Parent parent = m.getParent();
|
||||
|
||||
if ( parent != null )
|
||||
{
|
||||
validateStringNotEmpty( "parent.version", problems, Severity.FATAL, Version.BASE, parent.getVersion(),
|
||||
parent );
|
||||
}
|
||||
}
|
||||
|
||||
private void validate30RawProfileActivation( ModelProblemCollector problems, Activation activation,
|
||||
String sourceHint, String prefix, String fieldName,
|
||||
|
@ -376,17 +396,6 @@ public class DefaultModelValidator
|
|||
|
||||
if ( request.getValidationLevel() >= ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 )
|
||||
{
|
||||
Set<String> modules = new HashSet<>();
|
||||
for ( int i = 0, n = m.getModules().size(); i < n; i++ )
|
||||
{
|
||||
String module = m.getModules().get( i );
|
||||
if ( !modules.add( module ) )
|
||||
{
|
||||
addViolation( problems, Severity.ERROR, Version.V20, "modules.module[" + i + "]", null,
|
||||
"specifies duplicate child module " + module, m.getLocation( "modules" ) );
|
||||
}
|
||||
}
|
||||
|
||||
Severity errOn31 = getSeverity( request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_1 );
|
||||
|
||||
validateBannedCharacters( EMPTY, "version", problems, errOn31, Version.V20, m.getVersion(), null, m,
|
||||
|
|
|
@ -30,10 +30,22 @@ import org.apache.maven.model.building.ModelProblemCollector;
|
|||
*/
|
||||
public interface ModelValidator
|
||||
{
|
||||
/**
|
||||
* Checks the specified file model for missing or invalid values. This model is directly created from the POM
|
||||
* file and has not been subjected to inheritance, interpolation or profile/default injection.
|
||||
*
|
||||
* @param model The model to validate, must not be {@code null}.
|
||||
* @param request The model building request that holds further settings, must not be {@code null}.
|
||||
* @param problems The container used to collect problems that were encountered, must not be {@code null}.
|
||||
*/
|
||||
default void validateFileModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems )
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the specified (raw) model for missing or invalid values. The raw model is directly created from the POM
|
||||
* file and has not been subjected to inheritance, interpolation or profile/default injection.
|
||||
* Checks the specified (raw) model for missing or invalid values. The raw model is the file model + buildpom filter
|
||||
* transformation and has not been subjected to inheritance, interpolation or profile/default injection.
|
||||
*
|
||||
* @param model The model to validate, must not be {@code null}.
|
||||
* @param request The model building request that holds further settings, must not be {@code null}.
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
package org.apache.maven.model.building;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.apache.maven.model.building.DefaultModelBuilder.FileToRawModelMerger;
|
||||
import org.apache.maven.model.merge.ModelMerger;
|
||||
import org.junit.Test;
|
||||
|
||||
public class FileToRawModelMergerTest
|
||||
{
|
||||
|
||||
/**
|
||||
* Ensures that all list-merge methods are overridden
|
||||
*/
|
||||
@Test
|
||||
public void testOverriddenMergeMethods()
|
||||
{
|
||||
List<String> methodNames =
|
||||
Stream.of( ModelMerger.class.getDeclaredMethods() )
|
||||
.filter( m -> m.getName().startsWith( "merge" ) )
|
||||
.filter( m ->
|
||||
{
|
||||
String baseName = m.getName().substring( 5 /* merge */ );
|
||||
String entity = baseName.substring( baseName.indexOf( '_' ) + 1 );
|
||||
try
|
||||
{
|
||||
Type returnType = m.getParameterTypes()[0].getMethod( "get" + entity ).getGenericReturnType();
|
||||
if ( returnType instanceof ParameterizedType )
|
||||
{
|
||||
return !( (ParameterizedType) returnType ).getActualTypeArguments()[0].equals( String.class );
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch ( ReflectiveOperationException | SecurityException e )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
} )
|
||||
.map( Method::getName )
|
||||
.collect( Collectors.toList() );
|
||||
|
||||
List<String> overriddenMethods =
|
||||
Stream.of( FileToRawModelMerger.class.getDeclaredMethods() )
|
||||
.map( Method::getName )
|
||||
.filter( m -> m.startsWith( "merge" ) )
|
||||
.collect( Collectors.toList() );
|
||||
|
||||
assertThat( overriddenMethods, hasItems( methodNames.toArray( new String[0] ) ) );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -20,18 +20,24 @@ package org.apache.maven.model.inheritance;
|
|||
*/
|
||||
|
||||
import org.apache.maven.model.Model;
|
||||
import org.apache.maven.model.building.AbstractModelSourceTransformer;
|
||||
import org.apache.maven.model.building.SimpleProblemCollector;
|
||||
import org.apache.maven.model.building.TransformerContext;
|
||||
import org.apache.maven.model.io.DefaultModelReader;
|
||||
import org.apache.maven.model.io.DefaultModelWriter;
|
||||
import org.apache.maven.model.io.ModelReader;
|
||||
import org.apache.maven.model.io.ModelWriter;
|
||||
|
||||
import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xmlunit.matchers.CompareMatcher;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
@ -41,7 +47,7 @@ import static org.junit.Assert.assertThat;
|
|||
public class DefaultInheritanceAssemblerTest
|
||||
extends TestCase
|
||||
{
|
||||
private ModelReader reader;
|
||||
private DefaultModelReader reader;
|
||||
|
||||
private ModelWriter writer;
|
||||
|
||||
|
@ -54,6 +60,15 @@ public class DefaultInheritanceAssemblerTest
|
|||
super.setUp();
|
||||
|
||||
reader = new DefaultModelReader();
|
||||
reader.setTransformer( new AbstractModelSourceTransformer()
|
||||
{
|
||||
@Override
|
||||
protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
|
||||
throws TransformerConfigurationException, SAXException, ParserConfigurationException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
} );
|
||||
writer = new DefaultModelWriter();
|
||||
assembler = new DefaultInheritanceAssembler();
|
||||
}
|
||||
|
|
|
@ -64,10 +64,14 @@ public class DefaultModelValidatorTest
|
|||
throws Exception
|
||||
{
|
||||
ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level );
|
||||
|
||||
Model model = read( pom );
|
||||
|
||||
SimpleProblemCollector problems = new SimpleProblemCollector( read( pom ) );
|
||||
SimpleProblemCollector problems = new SimpleProblemCollector( model );
|
||||
|
||||
request.setFileModel( model );
|
||||
|
||||
validator.validateEffectiveModel( problems.getModel(), request, problems );
|
||||
validator.validateEffectiveModel( model, request, problems );
|
||||
|
||||
return problems;
|
||||
}
|
||||
|
@ -77,9 +81,15 @@ public class DefaultModelValidatorTest
|
|||
{
|
||||
ModelBuildingRequest request = new DefaultModelBuildingRequest().setValidationLevel( level );
|
||||
|
||||
SimpleProblemCollector problems = new SimpleProblemCollector( read( pom ) );
|
||||
Model model = read( pom );
|
||||
|
||||
SimpleProblemCollector problems = new SimpleProblemCollector( model );
|
||||
|
||||
validator.validateRawModel( problems.getModel(), request, problems );
|
||||
validator.validateFileModel( model, request, problems );
|
||||
|
||||
request.setFileModel( model );
|
||||
|
||||
validator.validateRawModel( model, request, problems );
|
||||
|
||||
return problems;
|
||||
}
|
||||
|
@ -366,7 +376,7 @@ public class DefaultModelValidatorTest
|
|||
public void testDuplicateModule()
|
||||
throws Exception
|
||||
{
|
||||
SimpleProblemCollector result = validate( "duplicate-module.xml" );
|
||||
SimpleProblemCollector result = validateRaw( "duplicate-module.xml" );
|
||||
|
||||
assertViolations( result, 0, 1, 0 );
|
||||
|
||||
|
@ -416,7 +426,6 @@ public class DefaultModelValidatorTest
|
|||
SimpleProblemCollector result = validateRaw( "incomplete-parent.xml" );
|
||||
|
||||
assertViolations( result, 3, 0, 0 );
|
||||
|
||||
assertTrue( result.getFatals().get( 0 ).contains( "parent.groupId" ) );
|
||||
assertTrue( result.getFatals().get( 1 ).contains( "parent.artifactId" ) );
|
||||
assertTrue( result.getFatals().get( 2 ).contains( "parent.version" ) );
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!--
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven</artifactId>
|
||||
<version>3.7.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>maven-xml</artifactId>
|
||||
<name>Maven XML</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,118 @@
|
|||
package org.apache.maven.xml;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.parsers.SAXParser;
|
||||
import javax.xml.parsers.SAXParserFactory;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXNotRecognizedException;
|
||||
import org.xml.sax.SAXNotSupportedException;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
/**
|
||||
* Creates XML related factories with OWASP advices applied
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public final class Factories
|
||||
{
|
||||
private Factories()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return
|
||||
* @see https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory
|
||||
*/
|
||||
public static TransformerFactory newTransformerFactory()
|
||||
{
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_DTD, "" );
|
||||
tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "" );
|
||||
|
||||
return tf;
|
||||
}
|
||||
|
||||
public static SAXParserFactory newSAXParserFactory()
|
||||
{
|
||||
SAXParserFactory spf = SAXParserFactory.newInstance();
|
||||
|
||||
try
|
||||
{
|
||||
// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
|
||||
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
|
||||
|
||||
// Using the SAXParserFactory's setFeature
|
||||
spf.setFeature( "http://xml.org/sax/features/external-general-entities", false );
|
||||
|
||||
// Xerces 2 only - http://xerces.apache.org/xerces-j/features.html#external-general-entities
|
||||
spf.setFeature( "http://apache.org/xml/features/disallow-doctype-decl", true );
|
||||
}
|
||||
catch ( ParserConfigurationException e )
|
||||
{
|
||||
// Tried an unsupported feature.
|
||||
}
|
||||
catch ( SAXNotRecognizedException e )
|
||||
{
|
||||
// Tried an unknown feature.
|
||||
}
|
||||
catch ( SAXNotSupportedException e )
|
||||
{
|
||||
// Tried a feature known to the parser but unsupported.
|
||||
}
|
||||
return spf;
|
||||
}
|
||||
|
||||
public static SAXParser newSAXParser() throws ParserConfigurationException, SAXException
|
||||
{
|
||||
SAXParser saxParser = newSAXParserFactory().newSAXParser();
|
||||
|
||||
return saxParser;
|
||||
}
|
||||
|
||||
public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException
|
||||
{
|
||||
XMLReader reader = newSAXParser().getXMLReader();
|
||||
|
||||
try
|
||||
{
|
||||
// Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
|
||||
// Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
|
||||
|
||||
// Using the XMLReader's setFeature
|
||||
reader.setFeature( "http://xml.org/sax/features/external-general-entities", false );
|
||||
}
|
||||
catch ( SAXNotRecognizedException e )
|
||||
{
|
||||
// Tried an unknown feature.
|
||||
}
|
||||
catch ( SAXNotSupportedException e )
|
||||
{
|
||||
// Tried a feature known to the parser but unsupported.
|
||||
}
|
||||
return reader;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package org.apache.maven.xml.sax;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Command pattern to gather events which can be executed later on.
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface SAXEvent
|
||||
{
|
||||
void execute() throws SAXException;
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package org.apache.maven.xml.sax;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Factory for SAXEvents
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public final class SAXEventFactory
|
||||
{
|
||||
private final ContentHandler contentHandler;
|
||||
|
||||
private final LexicalHandler lexicalHandler;
|
||||
|
||||
protected SAXEventFactory( ContentHandler contentHandler, LexicalHandler lexicalHandler )
|
||||
{
|
||||
this.contentHandler = contentHandler;
|
||||
this.lexicalHandler = lexicalHandler;
|
||||
}
|
||||
|
||||
public SAXEvent characters( final char[] ch, final int start, final int length )
|
||||
{
|
||||
final char[] txt = new char[length];
|
||||
System.arraycopy( ch, start, txt, 0, length );
|
||||
return () -> contentHandler.characters( txt, 0, length );
|
||||
}
|
||||
|
||||
public SAXEvent endDocument()
|
||||
{
|
||||
return () -> contentHandler.endDocument();
|
||||
}
|
||||
|
||||
public SAXEvent endElement( final String uri, final String localName, final String qName )
|
||||
{
|
||||
return () -> contentHandler.endElement( uri, localName, qName );
|
||||
}
|
||||
|
||||
public SAXEvent endPrefixMapping( final String prefix )
|
||||
{
|
||||
return () -> contentHandler.endPrefixMapping( prefix );
|
||||
}
|
||||
|
||||
public SAXEvent ignorableWhitespace( final char[] ch, final int start, final int length )
|
||||
{
|
||||
return () -> contentHandler.ignorableWhitespace( ch, start, length );
|
||||
}
|
||||
|
||||
public SAXEvent processingInstruction( final String target, final String data )
|
||||
{
|
||||
return () -> contentHandler.processingInstruction( target, data );
|
||||
}
|
||||
|
||||
public SAXEvent setDocumentLocator( final Locator locator )
|
||||
{
|
||||
return () -> contentHandler.setDocumentLocator( locator );
|
||||
}
|
||||
|
||||
public SAXEvent skippedEntity( final String name )
|
||||
{
|
||||
return () -> contentHandler.skippedEntity( name );
|
||||
}
|
||||
|
||||
public SAXEvent startDocument()
|
||||
{
|
||||
return () -> contentHandler.startDocument();
|
||||
}
|
||||
|
||||
public SAXEvent startElement( final String uri, final String localName, final String qName, final Attributes atts )
|
||||
{
|
||||
return () -> contentHandler.startElement( uri, localName, qName, atts );
|
||||
}
|
||||
|
||||
public SAXEvent startPrefixMapping( final String prefix, final String uri )
|
||||
{
|
||||
return () -> contentHandler.startPrefixMapping( prefix, uri );
|
||||
}
|
||||
|
||||
public static SAXEventFactory newInstance( ContentHandler contentHandler, LexicalHandler lexicalHandler )
|
||||
{
|
||||
return new SAXEventFactory( contentHandler, lexicalHandler );
|
||||
}
|
||||
|
||||
public SAXEvent startDTD( String name, String publicId, String systemId )
|
||||
{
|
||||
return () -> lexicalHandler.startDTD( name, publicId, systemId );
|
||||
}
|
||||
|
||||
public SAXEvent endDTD()
|
||||
{
|
||||
return () -> lexicalHandler.endDTD();
|
||||
}
|
||||
|
||||
public SAXEvent startEntity( String name )
|
||||
{
|
||||
return () -> lexicalHandler.startEntity( name );
|
||||
}
|
||||
|
||||
public SAXEvent endEntity( String name )
|
||||
{
|
||||
return () -> lexicalHandler.endEntity( name );
|
||||
|
||||
}
|
||||
|
||||
public SAXEvent startCDATA()
|
||||
{
|
||||
return () -> lexicalHandler.startCDATA();
|
||||
}
|
||||
|
||||
public SAXEvent endCDATA()
|
||||
{
|
||||
return () -> lexicalHandler.endCDATA();
|
||||
}
|
||||
|
||||
public SAXEvent comment( char[] ch, int start, int length )
|
||||
{
|
||||
final char[] txt = new char[length];
|
||||
System.arraycopy( ch, start, txt, 0, length );
|
||||
return () -> lexicalHandler.comment( txt, 0, length );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.apache.maven.xml.sax;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Utility class for SAXEvents
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public final class SAXEventUtils
|
||||
{
|
||||
private static final Pattern PATTERN = Pattern.compile( "[^:]+$" );
|
||||
|
||||
private SAXEventUtils()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the newLocalName prefixed with the namespace of the oldQName if present
|
||||
*
|
||||
* @param oldQName the QName, used for its namespace
|
||||
* @param newLocalName the preferred localName
|
||||
* @return the new QName
|
||||
*/
|
||||
public static String renameQName( String oldQName, String newLocalName )
|
||||
{
|
||||
return PATTERN.matcher( oldQName ).replaceFirst( newLocalName );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package org.apache.maven.xml.sax.ext;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* During parsing the line separators are transformed to \n
|
||||
* Unlike characters(), comments don't use the systems line separator for serialization.
|
||||
* Hence use this class in the LexicalHandler chain to do so
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class CommentRenormalizer implements LexicalHandler
|
||||
{
|
||||
private final LexicalHandler lexicalHandler;
|
||||
|
||||
private final String lineSeparator;
|
||||
|
||||
public CommentRenormalizer( LexicalHandler lexicalHandler )
|
||||
{
|
||||
this( lexicalHandler, System.lineSeparator() );
|
||||
}
|
||||
|
||||
// for testing purpose
|
||||
CommentRenormalizer( LexicalHandler lexicalHandler, String lineSeparator )
|
||||
{
|
||||
this.lexicalHandler = lexicalHandler;
|
||||
this.lineSeparator = lineSeparator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void comment( char[] ch, int start, int length )
|
||||
throws SAXException
|
||||
{
|
||||
if ( "\n".equals( lineSeparator ) )
|
||||
{
|
||||
lexicalHandler.comment( ch, start, length );
|
||||
}
|
||||
else
|
||||
{
|
||||
char[] ca = new String( ch, start, length ).replaceAll( "\n", lineSeparator ).toCharArray();
|
||||
|
||||
lexicalHandler.comment( ca, 0, ca.length );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDTD( String name, String publicId, String systemId )
|
||||
throws SAXException
|
||||
{
|
||||
lexicalHandler.startDTD( name, publicId, systemId );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDTD()
|
||||
throws SAXException
|
||||
{
|
||||
lexicalHandler.endDTD();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEntity( String name )
|
||||
throws SAXException
|
||||
{
|
||||
lexicalHandler.startEntity( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endEntity( String name )
|
||||
throws SAXException
|
||||
{
|
||||
lexicalHandler.endEntity( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
lexicalHandler.startCDATA();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
lexicalHandler.endCDATA();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,289 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Queue;
|
||||
|
||||
import org.apache.maven.xml.sax.SAXEvent;
|
||||
import org.apache.maven.xml.sax.SAXEventFactory;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Builds up a list of SAXEvents, which will be executed with {@link #executeEvents()}
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
abstract class AbstractEventXMLFilter extends AbstractSAXFilter
|
||||
{
|
||||
private Queue<SAXEvent> saxEvents = new ArrayDeque<>();
|
||||
|
||||
private SAXEventFactory eventFactory;
|
||||
|
||||
// characters BEFORE startElement must get state of startingElement
|
||||
// this way removing based on state keeps correct formatting
|
||||
private SAXEvent characters;
|
||||
|
||||
private boolean lockCharacters = false;
|
||||
|
||||
protected abstract boolean isParsing();
|
||||
|
||||
protected abstract String getState();
|
||||
|
||||
protected boolean acceptEvent( String state )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AbstractEventXMLFilter()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
<T extends XMLReader & LexicalHandler> AbstractEventXMLFilter( T parent )
|
||||
{
|
||||
setParent( parent );
|
||||
}
|
||||
|
||||
private SAXEventFactory getEventFactory()
|
||||
{
|
||||
if ( eventFactory == null )
|
||||
{
|
||||
eventFactory = SAXEventFactory.newInstance( getContentHandler(), getLexicalHandler() );
|
||||
}
|
||||
return eventFactory;
|
||||
}
|
||||
|
||||
private void processEvent( final SAXEvent event )
|
||||
throws SAXException
|
||||
{
|
||||
if ( isParsing() )
|
||||
{
|
||||
final String eventState = getState();
|
||||
final SAXEvent charactersEvent = characters;
|
||||
|
||||
if ( !lockCharacters && charactersEvent != null )
|
||||
{
|
||||
saxEvents.add( () ->
|
||||
{
|
||||
if ( acceptEvent( eventState ) )
|
||||
{
|
||||
charactersEvent.execute();
|
||||
}
|
||||
} );
|
||||
characters = null;
|
||||
}
|
||||
|
||||
saxEvents.add( () ->
|
||||
{
|
||||
if ( acceptEvent( eventState ) )
|
||||
{
|
||||
event.execute();
|
||||
}
|
||||
} );
|
||||
}
|
||||
else
|
||||
{
|
||||
event.execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be used to include extra events before a closing element.
|
||||
* This is a lightweight solution to keep the correct indentation.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected Includer include()
|
||||
{
|
||||
this.lockCharacters = true;
|
||||
|
||||
return () -> lockCharacters = false;
|
||||
}
|
||||
|
||||
protected final void executeEvents() throws SAXException
|
||||
{
|
||||
final String eventState = getState();
|
||||
final SAXEvent charactersEvent = characters;
|
||||
if ( charactersEvent != null )
|
||||
{
|
||||
saxEvents.add( () ->
|
||||
{
|
||||
if ( acceptEvent( eventState ) )
|
||||
{
|
||||
charactersEvent.execute();
|
||||
}
|
||||
} );
|
||||
characters = null;
|
||||
}
|
||||
|
||||
// not with streams due to checked SAXException
|
||||
while ( !saxEvents.isEmpty() )
|
||||
{
|
||||
saxEvents.poll().execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDocumentLocator( Locator locator )
|
||||
{
|
||||
try
|
||||
{
|
||||
processEvent( getEventFactory().setDocumentLocator( locator ) );
|
||||
}
|
||||
catch ( SAXException e )
|
||||
{
|
||||
// noop, setDocumentLocator can never throw a SAXException
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDocument() throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().startDocument() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().endDocument() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startPrefixMapping( String prefix, String uri ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().startPrefixMapping( prefix, uri ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endPrefixMapping( String prefix ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().endPrefixMapping( prefix ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, String localName, String qName, Attributes atts ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().startElement( uri, localName, qName, atts ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, String localName, String qName ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().endElement( uri, localName, qName ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters( char[] ch, int start, int length ) throws SAXException
|
||||
{
|
||||
if ( lockCharacters )
|
||||
{
|
||||
processEvent( getEventFactory().characters( ch, start, length ) );
|
||||
}
|
||||
else if ( isParsing() )
|
||||
{
|
||||
this.characters = getEventFactory().characters( ch, start, length );
|
||||
}
|
||||
else
|
||||
{
|
||||
super.characters( ch, start, length );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void ignorableWhitespace( char[] ch, int start, int length ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().ignorableWhitespace( ch, start, length ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processingInstruction( String target, String data ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().processingInstruction( target, data ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skippedEntity( String name ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().skippedEntity( name ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDTD( String name, String publicId, String systemId ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().startCDATA() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDTD() throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().endDTD() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEntity( String name ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().startEntity( name ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endEntity( String name ) throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().endEntity( name ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().startCDATA() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().endCDATA() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void comment( char[] ch, int start, int length )
|
||||
throws SAXException
|
||||
{
|
||||
processEvent( getEventFactory().comment( ch, start, length ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoCloseable with a close method that doesn't throw an exception
|
||||
*
|
||||
* @author Robert Scholte
|
||||
*
|
||||
*/
|
||||
@FunctionalInterface
|
||||
protected interface Includer extends AutoCloseable
|
||||
{
|
||||
void close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
import org.xml.sax.helpers.XMLFilterImpl;
|
||||
|
||||
/**
|
||||
* XMLFilter with LexicalHandler.
|
||||
* Since some filters collect events before processing them, the LexicalHandler events must be collected too.
|
||||
* Otherwise the LexicalHandler events might end up before all collected XMLReader events.
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class AbstractSAXFilter extends XMLFilterImpl implements LexicalHandler
|
||||
{
|
||||
private LexicalHandler lexicalHandler;
|
||||
|
||||
AbstractSAXFilter()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public <T extends XMLReader & LexicalHandler> AbstractSAXFilter( T parent )
|
||||
{
|
||||
setParent( parent );
|
||||
setLexicalHandler( parent );
|
||||
}
|
||||
|
||||
public LexicalHandler getLexicalHandler()
|
||||
{
|
||||
return lexicalHandler;
|
||||
}
|
||||
|
||||
public void setLexicalHandler( LexicalHandler lexicalHandler )
|
||||
{
|
||||
this.lexicalHandler = lexicalHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startDTD( String name, String publicId, String systemId )
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.startDTD( name, publicId, systemId );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endDTD()
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.endDTD();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startEntity( String name )
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.startEntity( name );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endEntity( String name )
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.endEntity( name );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.startCDATA();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endCDATA()
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.endCDATA();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void comment( char[] ch, int start, int length )
|
||||
throws SAXException
|
||||
{
|
||||
if ( lexicalHandler != null )
|
||||
{
|
||||
lexicalHandler.comment( ch, start, length );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Filter to adjust pom on filesystem before being processed for effective pom.
|
||||
* There should only be 1 BuildPomXMLFilter, so the same is being used by both
|
||||
* org.apache.maven.model.building.DefaultModelBuilder.transformData(InputStream) and
|
||||
* org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory.newFileTransformerManager()
|
||||
*
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class BuildPomXMLFilter extends AbstractSAXFilter
|
||||
{
|
||||
BuildPomXMLFilter()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
<T extends XMLReader & LexicalHandler> BuildPomXMLFilter( T parent )
|
||||
{
|
||||
super( parent );
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow overwriting parent
|
||||
*/
|
||||
@Override
|
||||
public final void setParent( XMLReader parent )
|
||||
{
|
||||
if ( getParent() == null )
|
||||
{
|
||||
super.setParent( parent );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.sax.SAXTransformerFactory;
|
||||
|
||||
import org.apache.maven.xml.Factories;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Base implementation for providing the BuildPomXML.
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class BuildPomXMLFilterFactory
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @param projectFile will be used by ConsumerPomXMLFilter to get the right filter
|
||||
* @return
|
||||
* @throws SAXException
|
||||
* @throws ParserConfigurationException
|
||||
* @throws TransformerConfigurationException
|
||||
*/
|
||||
public final BuildPomXMLFilter get( Path projectFile )
|
||||
throws SAXException, ParserConfigurationException, TransformerConfigurationException
|
||||
{
|
||||
AbstractSAXFilter parent = new AbstractSAXFilter();
|
||||
parent.setParent( getXMLReader() );
|
||||
parent.setLexicalHandler( getLexicalHander() );
|
||||
|
||||
if ( getDependencyKeyToVersionMapper() != null )
|
||||
{
|
||||
ReactorDependencyXMLFilter reactorDependencyXMLFilter =
|
||||
new ReactorDependencyXMLFilter( getDependencyKeyToVersionMapper() );
|
||||
reactorDependencyXMLFilter.setParent( parent );
|
||||
reactorDependencyXMLFilter.setLexicalHandler( parent );
|
||||
parent = reactorDependencyXMLFilter;
|
||||
}
|
||||
|
||||
if ( getRelativePathMapper() != null )
|
||||
{
|
||||
ParentXMLFilter parentFilter = new ParentXMLFilter( getRelativePathMapper() );
|
||||
parentFilter.setProjectPath( projectFile.getParent() );
|
||||
parentFilter.setParent( parent );
|
||||
parentFilter.setLexicalHandler( parent );
|
||||
parent = parentFilter;
|
||||
}
|
||||
|
||||
return new BuildPomXMLFilter( parent );
|
||||
}
|
||||
|
||||
private XMLReader getXMLReader() throws SAXException, ParserConfigurationException
|
||||
{
|
||||
XMLReader xmlReader = Factories.newXMLReader();
|
||||
xmlReader.setFeature( "http://xml.org/sax/features/namespaces", true );
|
||||
return xmlReader;
|
||||
}
|
||||
|
||||
private LexicalHandler getLexicalHander() throws TransformerConfigurationException
|
||||
{
|
||||
TransformerFactory transformerFactory = Factories.newTransformerFactory();
|
||||
if ( transformerFactory instanceof SAXTransformerFactory )
|
||||
{
|
||||
SAXTransformerFactory saxTransformerFactory = (SAXTransformerFactory) transformerFactory;
|
||||
return saxTransformerFactory.newTransformerHandler();
|
||||
}
|
||||
throw new TransformerConfigurationException( "Failed to get LexicalHandler via TransformerFactory:"
|
||||
+ " it is not an instance of SAXTransformerFactory" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the mapper or {@code null} if relativePaths don't need to be mapped
|
||||
*/
|
||||
protected Function<Path, Optional<RelativeProject>> getRelativePathMapper()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
protected BiFunction<String, String, String> getDependencyKeyToVersionMapper()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Listener can be used to capture the result of the build pom
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface BuildPomXMLFilterListener
|
||||
{
|
||||
/**
|
||||
* Captures the result of the XML transformation
|
||||
*
|
||||
* @param pomFile the original to being transformed
|
||||
* @param b the byte array
|
||||
* @param off the offset
|
||||
* @param len the length
|
||||
*/
|
||||
void write( Path pomFile, byte[] b, int off, int len );
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Resolves all ci-friendly properties occurrences
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class CiFriendlyXMLFilter
|
||||
extends AbstractSAXFilter
|
||||
{
|
||||
private Function<String, String> replaceChain = Function.identity();
|
||||
|
||||
public CiFriendlyXMLFilter setChangelist( String changelist )
|
||||
{
|
||||
replaceChain = replaceChain.andThen( t -> t.replace( "${changelist}", changelist ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public CiFriendlyXMLFilter setRevision( String revision )
|
||||
{
|
||||
replaceChain = replaceChain.andThen( t -> t.replace( "${revision}", revision ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
public CiFriendlyXMLFilter setSha1( String sha1 )
|
||||
{
|
||||
replaceChain = replaceChain.andThen( t -> t.replace( "${sha1}", sha1 ) );
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} is any of the ci properties is set, otherwise {@code false}
|
||||
*/
|
||||
public boolean isSet()
|
||||
{
|
||||
return !replaceChain.equals( Function.identity() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters( char[] ch, int start, int length )
|
||||
throws SAXException
|
||||
{
|
||||
String text = new String( ch, start, length );
|
||||
|
||||
// assuming this has the best performance
|
||||
if ( text.contains( "${" ) )
|
||||
{
|
||||
String newText = replaceChain.apply( text );
|
||||
|
||||
super.characters( newText.toCharArray(), 0, newText.length() );
|
||||
}
|
||||
else
|
||||
{
|
||||
super.characters( ch, start, length );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* XML Filter to transform pom.xml to consumer pom.
|
||||
* This often means stripping of build-specific information.
|
||||
* When extra information is required during filtering it is probably a member of the BuildPomXMLFilter
|
||||
*
|
||||
* This filter is used at 1 locations:
|
||||
* - {@link org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory} when publishing pom files.
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class ConsumerPomXMLFilter extends AbstractSAXFilter
|
||||
{
|
||||
<T extends XMLReader & LexicalHandler> ConsumerPomXMLFilter( T filter )
|
||||
{
|
||||
super( filter );
|
||||
}
|
||||
|
||||
/**
|
||||
* Don't allow overwriting parent
|
||||
*/
|
||||
@Override
|
||||
public final void setParent( XMLReader parent )
|
||||
{
|
||||
if ( getParent() == null )
|
||||
{
|
||||
super.setParent( parent );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class ConsumerPomXMLFilterFactory
|
||||
{
|
||||
private BuildPomXMLFilterFactory buildPomXMLFilterFactory;
|
||||
|
||||
public ConsumerPomXMLFilterFactory( BuildPomXMLFilterFactory buildPomXMLFilterFactory )
|
||||
{
|
||||
this.buildPomXMLFilterFactory = buildPomXMLFilterFactory;
|
||||
}
|
||||
|
||||
public final ConsumerPomXMLFilter get( Path projectPath )
|
||||
throws SAXException, ParserConfigurationException, TransformerConfigurationException
|
||||
{
|
||||
BuildPomXMLFilter parent = buildPomXMLFilterFactory.get( projectPath );
|
||||
|
||||
// Ensure that xs:any elements aren't touched by next filters
|
||||
AbstractSAXFilter filter = new FastForwardFilter( parent );
|
||||
|
||||
CiFriendlyXMLFilter ciFriendlyFilter = new CiFriendlyXMLFilter();
|
||||
getChangelist().ifPresent( ciFriendlyFilter::setChangelist );
|
||||
getRevision().ifPresent( ciFriendlyFilter::setRevision );
|
||||
getSha1().ifPresent( ciFriendlyFilter::setSha1 );
|
||||
|
||||
if ( ciFriendlyFilter.isSet() )
|
||||
{
|
||||
ciFriendlyFilter.setParent( parent );
|
||||
ciFriendlyFilter.setLexicalHandler( parent );
|
||||
filter = ciFriendlyFilter;
|
||||
}
|
||||
|
||||
// Strip modules
|
||||
filter = new ModulesXMLFilter( filter );
|
||||
// Adjust relativePath
|
||||
filter = new RelativePathXMLFilter( filter );
|
||||
|
||||
return new ConsumerPomXMLFilter( filter );
|
||||
}
|
||||
|
||||
// getters for the 3 magic properties of CIFriendly versions ( https://maven.apache.org/maven-ci-friendly.html )
|
||||
|
||||
protected Optional<String> getChangelist()
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
protected Optional<String> getRevision()
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
protected Optional<String> getSha1()
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class DependencyKey
|
||||
{
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
|
||||
private final int hashCode;
|
||||
|
||||
public DependencyKey( String groupId, String artifactId )
|
||||
{
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
|
||||
this.hashCode = Objects.hash( artifactId, groupId );
|
||||
}
|
||||
|
||||
public String getGroupId()
|
||||
{
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public String getArtifactId()
|
||||
{
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object obj )
|
||||
{
|
||||
if ( this == obj )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if ( obj == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( getClass() != obj.getClass() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
DependencyKey other = (DependencyKey) obj;
|
||||
|
||||
if ( !Objects.equals( artifactId, other.artifactId ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( !Objects.equals( groupId, other.groupId ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLFilter;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* This filter will skip all following filters and write directly to the output.
|
||||
* Should be used in case of a DOM that should not be effected by other filters, even though the elements match
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class FastForwardFilter extends AbstractSAXFilter
|
||||
{
|
||||
/**
|
||||
* DOM elements of pom
|
||||
*
|
||||
* <ul>
|
||||
* <li>execution.configuration</li>
|
||||
* <li>plugin.configuration</li>
|
||||
* <li>plugin.goals</li>
|
||||
* <li>profile.reports</li>
|
||||
* <li>project.reports</li>
|
||||
* <li>reportSet.configuration</li>
|
||||
* <ul>
|
||||
*/
|
||||
private final Deque<String> state = new ArrayDeque<>();
|
||||
|
||||
private int domDepth = 0;
|
||||
|
||||
private ContentHandler originalHandler;
|
||||
|
||||
FastForwardFilter()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
<T extends XMLReader & LexicalHandler> FastForwardFilter( T parent )
|
||||
{
|
||||
super( parent );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, String localName, String qName, Attributes atts )
|
||||
throws SAXException
|
||||
{
|
||||
super.startElement( uri, localName, qName, atts );
|
||||
if ( domDepth > 0 )
|
||||
{
|
||||
domDepth++;
|
||||
}
|
||||
else
|
||||
{
|
||||
final String key = state.peek() + '.' + localName;
|
||||
switch ( key )
|
||||
{
|
||||
case "execution.configuration":
|
||||
case "plugin.configuration":
|
||||
case "plugin.goals":
|
||||
case "profile.reports":
|
||||
case "project.reports":
|
||||
case "reportSet.configuration":
|
||||
domDepth++;
|
||||
|
||||
originalHandler = getContentHandler();
|
||||
|
||||
ContentHandler outputContentHandler = getContentHandler();
|
||||
while ( outputContentHandler instanceof XMLFilter )
|
||||
{
|
||||
outputContentHandler = ( (XMLFilter) outputContentHandler ).getContentHandler();
|
||||
}
|
||||
setContentHandler( outputContentHandler );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state.push( localName );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, String localName, String qName )
|
||||
throws SAXException
|
||||
{
|
||||
if ( domDepth > 0 )
|
||||
{
|
||||
domDepth--;
|
||||
|
||||
if ( domDepth == 0 )
|
||||
{
|
||||
setContentHandler( originalHandler );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state.pop();
|
||||
}
|
||||
super.endElement( uri, localName, qName );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Remove all modules, this is just buildtime information
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class ModulesXMLFilter
|
||||
extends AbstractEventXMLFilter
|
||||
{
|
||||
private boolean parsingModules;
|
||||
|
||||
private String state;
|
||||
|
||||
ModulesXMLFilter()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
<T extends XMLReader & LexicalHandler> ModulesXMLFilter( T parent )
|
||||
{
|
||||
super( parent );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, String localName, String qName, Attributes atts )
|
||||
throws SAXException
|
||||
{
|
||||
if ( !parsingModules && "modules".equals( localName ) )
|
||||
{
|
||||
parsingModules = true;
|
||||
}
|
||||
|
||||
if ( parsingModules )
|
||||
{
|
||||
state = localName;
|
||||
}
|
||||
|
||||
super.startElement( uri, localName, qName, atts );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, String localName, String qName )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingModules )
|
||||
{
|
||||
switch ( localName )
|
||||
{
|
||||
case "modules":
|
||||
executeEvents();
|
||||
|
||||
parsingModules = false;
|
||||
break;
|
||||
default:
|
||||
super.endElement( uri, localName, qName );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
super.endElement( uri, localName, qName );
|
||||
}
|
||||
|
||||
// for this simple structure resetting to modules it sufficient
|
||||
state = "modules";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isParsing()
|
||||
{
|
||||
return parsingModules;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptEvent( String state )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.maven.xml.sax.SAXEventUtils;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Transforms relativePath to version.
|
||||
* We could decide to simply allow {@code <parent/>}, but let's require the GA for now for checking
|
||||
* This filter does NOT remove the relativePath (which is done by {@link RelativePathXMLFilter}, it will only
|
||||
* optionally include the version based on the path
|
||||
* </p>
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class ParentXMLFilter
|
||||
extends AbstractEventXMLFilter
|
||||
{
|
||||
private boolean parsingParent;
|
||||
|
||||
// states
|
||||
private String state;
|
||||
|
||||
// whiteSpace after <parent>, to be used to position <version>
|
||||
private String parentWhitespace = "";
|
||||
|
||||
private String groupId;
|
||||
|
||||
private String artifactId;
|
||||
|
||||
private String relativePath;
|
||||
|
||||
private boolean hasVersion;
|
||||
|
||||
private Optional<RelativeProject> resolvedParent;
|
||||
|
||||
private final Function<Path, Optional<RelativeProject>> relativePathMapper;
|
||||
|
||||
private Path projectPath;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param relativePathMapper
|
||||
*/
|
||||
ParentXMLFilter( Function<Path, Optional<RelativeProject>> relativePathMapper )
|
||||
{
|
||||
this.relativePathMapper = relativePathMapper;
|
||||
}
|
||||
|
||||
public void setProjectPath( Path projectPath )
|
||||
{
|
||||
this.projectPath = projectPath;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isParsing()
|
||||
{
|
||||
return parsingParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, final String localName, String qName, Attributes atts )
|
||||
throws SAXException
|
||||
{
|
||||
if ( !parsingParent && "parent".equals( localName ) )
|
||||
{
|
||||
parsingParent = true;
|
||||
}
|
||||
|
||||
if ( parsingParent )
|
||||
{
|
||||
state = localName;
|
||||
|
||||
hasVersion |= "version".equals( localName );
|
||||
}
|
||||
|
||||
super.startElement( uri, localName, qName, atts );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters( char[] ch, int start, int length )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingParent )
|
||||
{
|
||||
final String eventState = state;
|
||||
|
||||
switch ( eventState )
|
||||
{
|
||||
case "parent":
|
||||
parentWhitespace = new String( ch, start, length );
|
||||
break;
|
||||
case "relativePath":
|
||||
relativePath = new String( ch, start, length );
|
||||
break;
|
||||
case "groupId":
|
||||
groupId = new String( ch, start, length );
|
||||
break;
|
||||
case "artifactId":
|
||||
artifactId = new String( ch, start, length );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
super.characters( ch, start, length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, final String localName, String qName )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingParent )
|
||||
{
|
||||
switch ( localName )
|
||||
{
|
||||
case "parent":
|
||||
if ( !hasVersion || relativePath != null )
|
||||
{
|
||||
resolvedParent =
|
||||
resolveRelativePath( Paths.get( Objects.toString( relativePath, "../pom.xml" ) ) );
|
||||
}
|
||||
|
||||
if ( !hasVersion && resolvedParent.isPresent() )
|
||||
{
|
||||
try ( Includer i = super.include() )
|
||||
{
|
||||
super.characters( parentWhitespace.toCharArray(), 0,
|
||||
parentWhitespace.length() );
|
||||
|
||||
String versionQName = SAXEventUtils.renameQName( qName, "version" );
|
||||
|
||||
super.startElement( uri, "version", versionQName, null );
|
||||
|
||||
String resolvedParentVersion = resolvedParent.get().getVersion();
|
||||
|
||||
super.characters( resolvedParentVersion.toCharArray(), 0,
|
||||
resolvedParentVersion.length() );
|
||||
|
||||
super.endElement( uri, "version", versionQName );
|
||||
}
|
||||
}
|
||||
super.executeEvents();
|
||||
|
||||
parsingParent = false;
|
||||
break;
|
||||
default:
|
||||
// marker?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
super.endElement( uri, localName, qName );
|
||||
state = "";
|
||||
}
|
||||
|
||||
protected Optional<RelativeProject> resolveRelativePath( Path relativePath )
|
||||
{
|
||||
Optional<RelativeProject> mappedProject =
|
||||
relativePathMapper.apply( projectPath.resolve( relativePath ).normalize() );
|
||||
|
||||
if ( mappedProject.isPresent() )
|
||||
{
|
||||
RelativeProject project = mappedProject.get();
|
||||
|
||||
if ( Objects.equals( groupId, project.getGroupId() )
|
||||
&& Objects.equals( artifactId, project.getArtifactId() ) )
|
||||
{
|
||||
return mappedProject;
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
import org.apache.maven.xml.sax.SAXEventUtils;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Will apply the version if the dependency is part of the reactor
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class ReactorDependencyXMLFilter extends AbstractEventXMLFilter
|
||||
{
|
||||
private boolean parsingDependency;
|
||||
|
||||
// states
|
||||
private String state;
|
||||
|
||||
// whiteSpace after <dependency>, to be used to position <version>
|
||||
private String dependencyWhitespace = "";
|
||||
|
||||
private boolean hasVersion;
|
||||
|
||||
private String groupId;
|
||||
|
||||
private String artifactId;
|
||||
|
||||
private final BiFunction<String, String, String> reactorVersionMapper;
|
||||
|
||||
public ReactorDependencyXMLFilter( BiFunction<String, String, String> reactorVersionMapper )
|
||||
{
|
||||
this.reactorVersionMapper = reactorVersionMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, String localName, String qName, Attributes atts )
|
||||
throws SAXException
|
||||
{
|
||||
if ( !parsingDependency && "dependency".equals( localName ) )
|
||||
{
|
||||
parsingDependency = true;
|
||||
}
|
||||
|
||||
if ( parsingDependency )
|
||||
{
|
||||
state = localName;
|
||||
|
||||
hasVersion |= "version".equals( localName );
|
||||
}
|
||||
super.startElement( uri, localName, qName, atts );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void characters( char[] ch, int start, int length )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingDependency )
|
||||
{
|
||||
final String eventState = state;
|
||||
switch ( eventState )
|
||||
{
|
||||
case "dependency":
|
||||
dependencyWhitespace = new String( ch, start, length );
|
||||
break;
|
||||
case "groupId":
|
||||
groupId = new String( ch, start, length );
|
||||
break;
|
||||
case "artifactId":
|
||||
artifactId = new String( ch, start, length );
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
super.characters( ch, start, length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, final String localName, String qName )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingDependency )
|
||||
{
|
||||
switch ( localName )
|
||||
{
|
||||
case "dependency":
|
||||
if ( !hasVersion )
|
||||
{
|
||||
String version = getVersion();
|
||||
|
||||
// dependency is not part of reactor, probably it is managed
|
||||
if ( version != null )
|
||||
{
|
||||
try ( Includer i = super.include() )
|
||||
{
|
||||
super.characters( dependencyWhitespace.toCharArray(), 0,
|
||||
dependencyWhitespace.length() );
|
||||
String versionQName = SAXEventUtils.renameQName( qName, "version" );
|
||||
|
||||
super.startElement( uri, "version", versionQName, null );
|
||||
super.characters( version.toCharArray(), 0, version.length() );
|
||||
super.endElement( uri, "version", versionQName );
|
||||
}
|
||||
}
|
||||
}
|
||||
super.executeEvents();
|
||||
|
||||
parsingDependency = false;
|
||||
|
||||
// reset
|
||||
hasVersion = false;
|
||||
groupId = null;
|
||||
artifactId = null;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
super.endElement( uri, localName, qName );
|
||||
|
||||
state = "";
|
||||
}
|
||||
|
||||
private String getVersion()
|
||||
{
|
||||
return reactorVersionMapper.apply( groupId, artifactId );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isParsing()
|
||||
{
|
||||
return parsingDependency;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
/**
|
||||
* Remove relativePath element, has no value for consumer pom
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
class RelativePathXMLFilter
|
||||
extends AbstractEventXMLFilter
|
||||
{
|
||||
private boolean parsingParent;
|
||||
|
||||
private String state;
|
||||
|
||||
RelativePathXMLFilter()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
<T extends XMLReader & LexicalHandler> RelativePathXMLFilter( T parent )
|
||||
{
|
||||
super( parent );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, final String localName, String qName, Attributes atts )
|
||||
throws SAXException
|
||||
{
|
||||
if ( !parsingParent && "parent".equals( localName ) )
|
||||
{
|
||||
parsingParent = true;
|
||||
}
|
||||
|
||||
if ( parsingParent )
|
||||
{
|
||||
state = localName;
|
||||
}
|
||||
|
||||
super.startElement( uri, localName, qName, atts );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, String localName, String qName )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingParent )
|
||||
{
|
||||
switch ( localName )
|
||||
{
|
||||
case "parent":
|
||||
executeEvents();
|
||||
|
||||
parsingParent = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
super.endElement( uri, localName, qName );
|
||||
|
||||
// for this simple structure resetting to parent it sufficient
|
||||
state = "parent";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isParsing()
|
||||
{
|
||||
return parsingParent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptEvent( String state )
|
||||
{
|
||||
return !"relativePath".equals( state );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Robert Scholte
|
||||
* @since 3.7.0
|
||||
*/
|
||||
public class RelativeProject
|
||||
{
|
||||
private final String groupId;
|
||||
|
||||
private final String artifactId;
|
||||
|
||||
private final String version;
|
||||
|
||||
public RelativeProject( String groupId, String artifactId, String version )
|
||||
{
|
||||
this.groupId = groupId;
|
||||
this.artifactId = artifactId;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getGroupId()
|
||||
{
|
||||
return groupId;
|
||||
}
|
||||
|
||||
public String getArtifactId()
|
||||
{
|
||||
return artifactId;
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return version;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.apache.maven.xml.sax;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import org.apache.maven.xml.sax.SAXEventUtils;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class SAXEventUtilsTest
|
||||
{
|
||||
@Test
|
||||
public void replaceWithNamespace()
|
||||
{
|
||||
assertThat( SAXEventUtils.renameQName( "org:bar", "com" ), is( "org:com" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void replaceWithoutNamespace()
|
||||
{
|
||||
assertThat( SAXEventUtils.renameQName( "bar", "com" ), is( "com" ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package org.apache.maven.xml.sax.ext;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
import org.xml.sax.ext.LexicalHandler;
|
||||
|
||||
@RunWith( Parameterized.class )
|
||||
public class CommentRenormalizerTest
|
||||
{
|
||||
private LexicalHandler lexicalHandler;
|
||||
|
||||
private final String lineSeparator;
|
||||
|
||||
@Parameters
|
||||
public static Collection<Object[]> data() {
|
||||
return Arrays.asList(new Object[][] {
|
||||
{ "\n" },
|
||||
{ "\r\n" },
|
||||
{ "\r" }
|
||||
});
|
||||
}
|
||||
|
||||
public CommentRenormalizerTest( String lineSeparator )
|
||||
{
|
||||
this.lineSeparator = lineSeparator;
|
||||
this.lexicalHandler = mock( LexicalHandler.class );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void singleLine()
|
||||
throws Exception
|
||||
{
|
||||
CommentRenormalizer commentRenormalizer = new CommentRenormalizer( lexicalHandler, lineSeparator );
|
||||
|
||||
char[] ch = "single line".toCharArray();
|
||||
|
||||
commentRenormalizer.comment( ch, 0, ch.length );
|
||||
|
||||
verify( lexicalHandler ).comment( ch, 0, ch.length );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multiLine()
|
||||
throws Exception
|
||||
{
|
||||
CommentRenormalizer commentRenormalizer = new CommentRenormalizer( lexicalHandler, lineSeparator );
|
||||
|
||||
String text = "I%sam%sthe%sbest%s";
|
||||
|
||||
char[] chIn = String.format( text, "\n", "\n", "\n", "\n" ).toCharArray();
|
||||
char[] chOut = String.format( text, lineSeparator, lineSeparator, lineSeparator, lineSeparator ).toCharArray();
|
||||
|
||||
commentRenormalizer.comment( chIn, 0, chIn.length );
|
||||
|
||||
verify( lexicalHandler ).comment( chOut, 0, chOut.length );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.OutputKeys;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.sax.SAXResult;
|
||||
import javax.xml.transform.sax.SAXSource;
|
||||
import javax.xml.transform.sax.SAXTransformerFactory;
|
||||
import javax.xml.transform.sax.TransformerHandler;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
|
||||
import org.apache.maven.xml.Factories;
|
||||
import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
public abstract class AbstractXMLFilterTests
|
||||
{
|
||||
public AbstractXMLFilterTests()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
protected abstract AbstractSAXFilter getFilter() throws TransformerException, SAXException, ParserConfigurationException;
|
||||
|
||||
private void setParent( AbstractSAXFilter filter ) throws SAXException, ParserConfigurationException
|
||||
{
|
||||
if( filter.getParent() == null )
|
||||
{
|
||||
XMLReader r = Factories.newXMLReader();
|
||||
|
||||
filter.setParent( r );
|
||||
filter.setFeature( "http://xml.org/sax/features/namespaces", true );
|
||||
}
|
||||
}
|
||||
|
||||
protected String omitXmlDeclaration() {
|
||||
return "yes";
|
||||
}
|
||||
|
||||
protected String indentAmount() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String transform( String input )
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
return transform( new StringReader( input ) );
|
||||
}
|
||||
|
||||
protected String transform( Reader input ) throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
AbstractSAXFilter filter = getFilter();
|
||||
setParent( filter );
|
||||
|
||||
return transform( input, filter );
|
||||
}
|
||||
|
||||
protected String transform( String input, AbstractSAXFilter filter )
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
setParent( filter );
|
||||
return transform( new StringReader( input ), filter );
|
||||
}
|
||||
|
||||
protected String transform( Reader input, AbstractSAXFilter filter )
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
Writer writer = new StringWriter();
|
||||
StreamResult result = new StreamResult( writer );
|
||||
|
||||
SAXTransformerFactory transformerFactory = (SAXTransformerFactory) Factories.newTransformerFactory();
|
||||
TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
|
||||
filter.setLexicalHandler( transformerHandler );
|
||||
transformerHandler.getTransformer().setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, omitXmlDeclaration() );
|
||||
if ( indentAmount() != null )
|
||||
{
|
||||
transformerHandler.getTransformer().setOutputProperty( OutputKeys.INDENT, "yes" );
|
||||
transformerHandler.getTransformer().setOutputProperty( "{http://xml.apache.org/xslt}indent-amount",
|
||||
indentAmount() );
|
||||
}
|
||||
transformerHandler.setResult( result );
|
||||
Transformer transformer = transformerFactory.newTransformer();
|
||||
|
||||
SAXSource transformSource = new SAXSource( filter, new InputSource( input ) );
|
||||
|
||||
SAXResult transformResult = new SAXResult( transformerHandler );
|
||||
transformResult.setLexicalHandler( filter );
|
||||
transformer.transform( transformSource, transformResult );
|
||||
|
||||
return writer.toString();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,235 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
|
||||
{
|
||||
@Override
|
||||
protected String omitXmlDeclaration()
|
||||
{
|
||||
return "no";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSAXFilter getFilter() throws SAXException, ParserConfigurationException, TransformerConfigurationException
|
||||
{
|
||||
final BuildPomXMLFilterFactory buildPomXMLFilterFactory = new BuildPomXMLFilterFactory()
|
||||
{
|
||||
@Override
|
||||
protected Function<Path, Optional<RelativeProject>> getRelativePathMapper()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BiFunction<String, String, String> getDependencyKeyToVersionMapper()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
ConsumerPomXMLFilter filter = new ConsumerPomXMLFilterFactory( buildPomXMLFilterFactory )
|
||||
{
|
||||
@Override
|
||||
protected Optional<String> getSha1()
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> getRevision()
|
||||
{
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> getChangelist()
|
||||
{
|
||||
return Optional.of( "CL" );
|
||||
}
|
||||
}.get( Paths.get( "pom.xml" ) );
|
||||
filter.setFeature( "http://xml.org/sax/features/namespaces", true );
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aggregatorWithParent() throws Exception {
|
||||
String input = "<project>\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>PARENT</artifactId>\n"
|
||||
+ " <version>VERSION</version>\n"
|
||||
+ " <relativePath>../pom.xml</relativePath>\n"
|
||||
+ " </parent>\n"
|
||||
+ " <artifactId>PROJECT</artifactId>\n"
|
||||
+ " <modules>\n"
|
||||
+ " <module>ab</module>\n"
|
||||
+ " <module>../cd</module>\n"
|
||||
+ " </modules>\n"
|
||||
+ "</project>";
|
||||
String expected = "<project>\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>PARENT</artifactId>\n"
|
||||
+ " <version>VERSION</version>\n"
|
||||
+ " </parent>\n"
|
||||
+ " <artifactId>PROJECT</artifactId>\n"
|
||||
+ "</project>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).ignoreWhitespace().areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aggregatorWithCliFriendlyVersion() throws Exception {
|
||||
String input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0\n" +
|
||||
" http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
|
||||
" <modelVersion>4.0.0</modelVersion>\n" +
|
||||
" <groupId>org.sonatype.mavenbook.multispring</groupId>\n" +
|
||||
" <artifactId>parent</artifactId>\n" +
|
||||
" <version>0.9-${changelist}-SNAPSHOT</version>\n" +
|
||||
" <packaging>pom</packaging>\n" +
|
||||
" <name>Multi-Spring Chapter Parent Project</name>\n" +
|
||||
" <modules>\n" +
|
||||
" <module>simple-parent</module>\n" +
|
||||
" </modules>\n" +
|
||||
" \n" +
|
||||
" <pluginRepositories>\n" +
|
||||
" <pluginRepository>\n" +
|
||||
" <id>apache.snapshots</id>\n" +
|
||||
" <url>http://repository.apache.org/snapshots/</url>\n" +
|
||||
" </pluginRepository>\n" +
|
||||
" </pluginRepositories>\n" +
|
||||
"</project>";
|
||||
String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0\n" +
|
||||
" http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
|
||||
" <modelVersion>4.0.0</modelVersion>\n" +
|
||||
" <groupId>org.sonatype.mavenbook.multispring</groupId>\n" +
|
||||
" <artifactId>parent</artifactId>\n" +
|
||||
" <version>0.9-CL-SNAPSHOT</version>\n" +
|
||||
" <packaging>pom</packaging>\n" +
|
||||
" <name>Multi-Spring Chapter Parent Project</name>\n" +
|
||||
" \n" +
|
||||
" <pluginRepositories>\n" +
|
||||
" <pluginRepository>\n" +
|
||||
" <id>apache.snapshots</id>\n" +
|
||||
" <url>http://repository.apache.org/snapshots/</url>\n" +
|
||||
" </pluginRepository>\n" +
|
||||
" </pluginRepositories>\n" +
|
||||
"</project>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).ignoreWhitespace().areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void licenseHeader() throws Exception {
|
||||
String input = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
||||
"\n" +
|
||||
"<!--\n" +
|
||||
"Licensed to the Apache Software Foundation (ASF) under one\n" +
|
||||
"or more contributor license agreements. See the NOTICE file\n" +
|
||||
"distributed with this work for additional information\n" +
|
||||
"regarding copyright ownership. The ASF licenses this file\n" +
|
||||
"to you under the Apache License, Version 2.0 (the\n" +
|
||||
"\"License\"); you may not use this file except in compliance\n" +
|
||||
"with the License. You may obtain a copy of the License at\n" +
|
||||
"\n" +
|
||||
" http://www.apache.org/licenses/LICENSE-2.0\n" +
|
||||
"\n" +
|
||||
"Unless required by applicable law or agreed to in writing,\n" +
|
||||
"software distributed under the License is distributed on an\n" +
|
||||
"\"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\n" +
|
||||
"KIND, either express or implied. See the License for the\n" +
|
||||
"specific language governing permissions and limitations\n" +
|
||||
"under the License.\n" +
|
||||
"-->\n" +
|
||||
"\n" +
|
||||
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n" +
|
||||
" <modelVersion>4.0.0</modelVersion>\n" +
|
||||
" <parent>\n" +
|
||||
" <groupId>org.apache.maven</groupId>\n" +
|
||||
" <artifactId>maven</artifactId>\n" +
|
||||
" <version>3.7.0-SNAPSHOT</version>\n" +
|
||||
" </parent>\n" +
|
||||
" <artifactId>maven-xml</artifactId>\n" +
|
||||
" <name>Maven XML</name>\n" +
|
||||
" \n" +
|
||||
" <properties>\n" +
|
||||
" <maven.compiler.source>1.8</maven.compiler.source>\n" +
|
||||
" <maven.compiler.target>1.8</maven.compiler.target>\n" +
|
||||
" </properties>\n" +
|
||||
"\n" +
|
||||
" <build>\n" +
|
||||
" <plugins>\n" +
|
||||
" <plugin>\n" +
|
||||
" <groupId>org.codehaus.mojo</groupId>\n" +
|
||||
" <artifactId>animal-sniffer-maven-plugin</artifactId>\n" +
|
||||
" <configuration>\n" +
|
||||
" <signature>\n" +
|
||||
" <groupId>org.codehaus.mojo.signature</groupId>\n" +
|
||||
" <artifactId>java18</artifactId>\n" +
|
||||
" <version>1.0</version>\n" +
|
||||
" </signature>\n" +
|
||||
" </configuration>\n" +
|
||||
" </plugin>\n" +
|
||||
" </plugins>\n" +
|
||||
" </build>\n" +
|
||||
" \n" +
|
||||
" <dependencies>\n" +
|
||||
" <dependency>\n" +
|
||||
" <groupId>javax.inject</groupId>\n" +
|
||||
" <artifactId>javax.inject</artifactId>\n" +
|
||||
" <optional>true</optional>\n" +
|
||||
" </dependency>\n" +
|
||||
" <dependency>\n" +
|
||||
" <groupId>org.xmlunit</groupId>\n" +
|
||||
" <artifactId>xmlunit-assertj</artifactId>\n" +
|
||||
" <scope>test</scope>\n" +
|
||||
" </dependency>\n" +
|
||||
" </dependencies>\n" +
|
||||
"</project>";
|
||||
String expected = input;
|
||||
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
|
||||
import org.apache.maven.xml.sax.filter.ModulesXMLFilter;
|
||||
import org.junit.Test;
|
||||
|
||||
public class ModulesXMLFilterTest extends AbstractXMLFilterTests {
|
||||
|
||||
@Override
|
||||
protected ModulesXMLFilter getFilter()
|
||||
{
|
||||
return new ModulesXMLFilter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyModules() throws Exception {
|
||||
String input = "<project><modules/></project>";
|
||||
String expected = "<project/>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setOfModules() throws Exception {
|
||||
String input = "<project><modules>"
|
||||
+ "<module>ab</module>"
|
||||
+ "<module>../cd</module>"
|
||||
+ "</modules></project>";
|
||||
String expected = "<project/>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noModules() throws Exception {
|
||||
String input = "<project><name>NAME</name></project>";
|
||||
String expected = input;
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comment() throws Exception {
|
||||
|
||||
String input = "<project><!--before--><modules>"
|
||||
+ "<!--pre-in-->"
|
||||
+ "<module><!--in-->ab</module>"
|
||||
+ "<module>../cd</module>"
|
||||
+ "<!--post-in-->"
|
||||
+ "</modules>"
|
||||
+ "<!--after--></project>";
|
||||
String expected = "<project><!--before--><!--after--></project>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setOfModulesLF() throws Exception {
|
||||
String input = "<project>\n"
|
||||
+ "\n"
|
||||
+ " <modules>\n"
|
||||
+ " <module>ab</module>\n"
|
||||
+ " <module>../cd</module>\n"
|
||||
+ " </modules>\n"
|
||||
+ "\n"
|
||||
+ "</project>\n";
|
||||
String expected = "<project>\n"
|
||||
+ "\n"
|
||||
+ " \n"
|
||||
+ "\n"
|
||||
+ "</project>\n";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,215 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.apache.maven.xml.sax.filter.ParentXMLFilter;
|
||||
import org.apache.maven.xml.sax.filter.RelativeProject;
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class ParentXMLFilterTest extends AbstractXMLFilterTests
|
||||
{
|
||||
@Override
|
||||
protected ParentXMLFilter getFilter()
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
ParentXMLFilter filter = new ParentXMLFilter( x -> Optional.of( new RelativeProject( "GROUPID",
|
||||
"ARTIFACTID",
|
||||
"1.0.0" ) ) );
|
||||
filter.setProjectPath( Paths.get( "pom.xml").toAbsolutePath() );
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMinimum() throws Exception
|
||||
{
|
||||
String input = "<parent/>";
|
||||
String expected = input;
|
||||
String actual = transform( input );
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoRelativePath() throws Exception
|
||||
{
|
||||
String input = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<version>VERSION</version>"
|
||||
+ "</parent>";
|
||||
String expected = input;
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultRelativePath() throws Exception
|
||||
{
|
||||
String input = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "</parent>";
|
||||
String expected = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<version>1.0.0</version>"
|
||||
+ "</parent>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoVersion() throws Exception
|
||||
{
|
||||
String input = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<relativePath>RELATIVEPATH</relativePath>"
|
||||
+ "</parent>";
|
||||
String expected = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<relativePath>RELATIVEPATH</relativePath>"
|
||||
+ "<version>1.0.0</version>"
|
||||
+ "</parent>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidRelativePath() throws Exception
|
||||
{
|
||||
ParentXMLFilter filter = new ParentXMLFilter( x -> Optional.ofNullable( null ) );
|
||||
filter.setProjectPath( Paths.get( "pom.xml").toAbsolutePath() );
|
||||
|
||||
String input = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<relativePath>RELATIVEPATH</relativePath>"
|
||||
+ "</parent>";
|
||||
String expected = input;
|
||||
|
||||
String actual = transform( input, filter );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelativePathAndVersion() throws Exception
|
||||
{
|
||||
String input = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<relativePath>RELATIVEPATH</relativePath>"
|
||||
+ "<version>1.0.0</version>"
|
||||
+ "</parent>";
|
||||
String expected = "<parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<relativePath>RELATIVEPATH</relativePath>"
|
||||
+ "<version>1.0.0</version>"
|
||||
+ "</parent>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithWeirdNamespace() throws Exception
|
||||
{
|
||||
String input = "<relativePath:parent xmlns:relativePath=\"relativePath\">"
|
||||
+ "<relativePath:groupId>GROUPID</relativePath:groupId>"
|
||||
+ "<relativePath:artifactId>ARTIFACTID</relativePath:artifactId>"
|
||||
+ "<relativePath:relativePath>RELATIVEPATH</relativePath:relativePath>"
|
||||
+ "</relativePath:parent>";
|
||||
String expected = "<relativePath:parent xmlns:relativePath=\"relativePath\">"
|
||||
+ "<relativePath:groupId>GROUPID</relativePath:groupId>"
|
||||
+ "<relativePath:artifactId>ARTIFACTID</relativePath:artifactId>"
|
||||
+ "<relativePath:relativePath>RELATIVEPATH</relativePath:relativePath>"
|
||||
+ "<relativePath:version>1.0.0</relativePath:version>"
|
||||
+ "</relativePath:parent>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void comment() throws Exception
|
||||
{
|
||||
String input = "<project><!--before--><parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<!--version here-->"
|
||||
+ "</parent>"
|
||||
+ "</project>";
|
||||
String expected = "<project><!--before--><parent>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<!--version here-->"
|
||||
+ "<version>1.0.0</version>"
|
||||
+ "</parent>"
|
||||
+ "</project>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIndent() throws Exception
|
||||
{
|
||||
String input = "<project>\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>ARTIFACTID</artifactId>\n"
|
||||
+ " <!--version here-->\n"
|
||||
+ " </parent>\n"
|
||||
+ "</project>";
|
||||
String expected = "<project>" + System.lineSeparator()
|
||||
+ " <parent>" + System.lineSeparator()
|
||||
+ " <groupId>GROUPID</groupId>" + System.lineSeparator()
|
||||
+ " <artifactId>ARTIFACTID</artifactId>" + System.lineSeparator()
|
||||
+ " <!--version here-->" + System.lineSeparator()
|
||||
+ " <version>1.0.0</version>" + System.lineSeparator()
|
||||
+ " </parent>" + System.lineSeparator()
|
||||
+ "</project>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertEquals( expected, actual );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class ReactorDependencyXMLFilterTest extends AbstractXMLFilterTests
|
||||
{
|
||||
@Override
|
||||
protected ReactorDependencyXMLFilter getFilter()
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
return new ReactorDependencyXMLFilter( (g, a) -> "1.0.0" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultDependency() throws Exception
|
||||
{
|
||||
String input = "<dependency>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<version>VERSION</version>"
|
||||
+ "</dependency>";
|
||||
String expected = input;
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertThat( actual ).isEqualTo( expected );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManagedDependency() throws Exception
|
||||
{
|
||||
ReactorDependencyXMLFilter filter = new ReactorDependencyXMLFilter( (g, a) -> null );
|
||||
|
||||
String input = "<dependency>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "</dependency>";
|
||||
String expected = input;
|
||||
|
||||
String actual = transform( input, filter );
|
||||
|
||||
assertThat( actual ).isEqualTo( expected );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactorDependency() throws Exception
|
||||
{
|
||||
String input = "<dependency>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "</dependency>";
|
||||
String expected = "<dependency>"
|
||||
+ "<groupId>GROUPID</groupId>"
|
||||
+ "<artifactId>ARTIFACTID</artifactId>"
|
||||
+ "<version>1.0.0</version>"
|
||||
+ "</dependency>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertThat( actual ).isEqualTo( expected );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReactorDependencyLF() throws Exception
|
||||
{
|
||||
String input = "<dependency>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>ARTIFACTID</artifactId>\n"
|
||||
+ " <!-- include version here --> "
|
||||
+ "</dependency>";
|
||||
String expected = "<dependency>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>ARTIFACTID</artifactId>\n"
|
||||
+ " <!-- include version here -->\n"
|
||||
+ " <version>1.0.0</version>\n"
|
||||
+ "</dependency>";
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertThat( actual ).and( expected ).ignoreWhitespace().areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void multipleDependencies() throws Exception {
|
||||
String input = "<project>\n" +
|
||||
" <modelVersion>4.0.0</modelVersion>\n" +
|
||||
" <groupId>tests.project</groupId>\n" +
|
||||
" <artifactId>duplicate-plugin-defs-merged</artifactId>\n" +
|
||||
" <version>1</version>\n" +
|
||||
" <build>\n" +
|
||||
" <plugins>\n" +
|
||||
" <plugin>\n" +
|
||||
" <artifactId>maven-compiler-plugin</artifactId>\n" +
|
||||
" <dependencies>\n" +
|
||||
" <dependency>\n" +
|
||||
" <groupId>group</groupId>\n" +
|
||||
" <artifactId>first</artifactId>\n" +
|
||||
" <version>1</version>\n" +
|
||||
" </dependency>\n" +
|
||||
" </dependencies>\n" +
|
||||
" </plugin>\n" +
|
||||
" <plugin>\n" +
|
||||
" <artifactId>maven-compiler-plugin</artifactId>\n" +
|
||||
" <dependencies>\n" +
|
||||
" <dependency>\n" +
|
||||
" <groupId>group</groupId>\n" +
|
||||
" <artifactId>second</artifactId>\n" +
|
||||
" <version>1</version>\n" +
|
||||
" </dependency>\n" +
|
||||
" </dependencies>\n" +
|
||||
" </plugin>\n" +
|
||||
" </plugins>\n" +
|
||||
" </build>\n" +
|
||||
"</project>";
|
||||
String expected = input;
|
||||
|
||||
String actual = transform( input );
|
||||
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package org.apache.maven.xml.sax.filter;
|
||||
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
import static org.xmlunit.assertj.XmlAssert.assertThat;
|
||||
|
||||
import org.apache.maven.xml.sax.filter.RelativePathXMLFilter;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RelativePathXMLFilterTest extends AbstractXMLFilterTests
|
||||
{
|
||||
@Override
|
||||
protected RelativePathXMLFilter getFilter()
|
||||
{
|
||||
return new RelativePathXMLFilter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelativePath() throws Exception
|
||||
{
|
||||
String input = "<project>\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>PARENT</artifactId>\n"
|
||||
+ " <version>VERSION</version>\n"
|
||||
+ " <relativePath>../pom.xml</relativePath>\n"
|
||||
+ " </parent>\n"
|
||||
+ " <artifactId>PROJECT</artifactId>\n"
|
||||
+ "</project>";
|
||||
String expected = "<project>\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>PARENT</artifactId>\n"
|
||||
+ " <version>VERSION</version>\n"
|
||||
+ " </parent>\n"
|
||||
+ " <artifactId>PROJECT</artifactId>\n"
|
||||
+ "</project>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelativePathNS() throws Exception
|
||||
{
|
||||
String input = "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>PARENT</artifactId>\n"
|
||||
+ " <version>VERSION</version>\n"
|
||||
+ " <relativePath>../pom.xml</relativePath>\n"
|
||||
+ " </parent>\n"
|
||||
+ " <artifactId>PROJECT</artifactId>\n"
|
||||
+ "</project>";
|
||||
String expected = "<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n"
|
||||
+ " <parent>\n"
|
||||
+ " <groupId>GROUPID</groupId>\n"
|
||||
+ " <artifactId>PARENT</artifactId>\n"
|
||||
+ " <version>VERSION</version>\n"
|
||||
+ " </parent>\n"
|
||||
+ " <artifactId>PROJECT</artifactId>\n"
|
||||
+ "</project>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRelativePathPasNS() throws Exception
|
||||
{
|
||||
String input = "<p:project xmlns:p=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n"
|
||||
+ " <p:parent>\n"
|
||||
+ " <p:groupId>GROUPID</p:groupId>\n"
|
||||
+ " <p:artifactId>PARENT</p:artifactId>\n"
|
||||
+ " <p:version>VERSION</p:version>\n"
|
||||
+ " <p:relativePath>../pom.xml</p:relativePath>\n"
|
||||
+ " </p:parent>\n"
|
||||
+ " <p:artifactId>PROJECT</p:artifactId>\n"
|
||||
+ "</p:project>";
|
||||
String expected = "<p:project xmlns:p=\"http://maven.apache.org/POM/4.0.0\"\n" +
|
||||
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
|
||||
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">\n"
|
||||
+ " <p:parent>\n"
|
||||
+ " <p:groupId>GROUPID</p:groupId>\n"
|
||||
+ " <p:artifactId>PARENT</p:artifactId>\n"
|
||||
+ " <p:version>VERSION</p:version>\n"
|
||||
+ " </p:parent>\n"
|
||||
+ " <p:artifactId>PROJECT</p:artifactId>\n"
|
||||
+ "</p:project>";
|
||||
String actual = transform( input );
|
||||
assertThat( actual ).and( expected ).areIdentical();
|
||||
}
|
||||
|
||||
}
|
12
pom.xml
12
pom.xml
|
@ -97,6 +97,7 @@ under the License.
|
|||
<module>apache-maven</module> <!-- rename to apache-maven/maven.pom after RAT-268 -->
|
||||
<module>maven-wrapper</module>
|
||||
<module>apache-maven/maven-wrapper.pom</module>
|
||||
<module>maven-xml</module>
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
|
@ -250,6 +251,11 @@ under the License.
|
|||
<artifactId>maven-slf4j-wrapper</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-xml</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!--bootstrap-end-comment-->
|
||||
<!-- Plexus -->
|
||||
<dependency>
|
||||
|
@ -419,6 +425,12 @@ under the License.
|
|||
<version>${mockitoVersion}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-assertj</artifactId>
|
||||
<version>${xmlunitVersion}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.xmlunit</groupId>
|
||||
<artifactId>xmlunit-core</artifactId>
|
||||
|
|
Loading…
Reference in New Issue