Skip to content

Commit

Permalink
#15 Support inclusion of services (uses/provides)
Browse files Browse the repository at this point in the history
  • Loading branch information
rfscholte committed Jun 21, 2018
1 parent e3b4c60 commit 9115ce8
Show file tree
Hide file tree
Showing 8 changed files with 311 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

Expand All @@ -38,9 +39,13 @@ public class JavaModuleDescriptor

private boolean automatic;

private Set<JavaRequires> requires = new LinkedHashSet<JavaRequires>();
private Set<JavaRequires> requires = new LinkedHashSet<>();

private Set<JavaExports> exports = new LinkedHashSet<JavaExports>();
private Set<JavaExports> exports = new LinkedHashSet<>();

private Set<String> uses = new LinkedHashSet<>();

private Set<JavaProvides> provides = new LinkedHashSet<>();

public String name()
{
Expand All @@ -62,6 +67,16 @@ public Set<JavaExports> exports()
return Collections.unmodifiableSet( exports );
}

public Set<JavaProvides> provides()
{
return Collections.unmodifiableSet( provides );
}

public Set<String> uses()
{
return Collections.unmodifiableSet( uses );
}

public static JavaModuleDescriptor.Builder newModule( String name )
{
return new Builder( name ).setAutomatic( false );
Expand Down Expand Up @@ -145,8 +160,7 @@ private Builder setAutomatic( boolean isAutomatic )
*/
public Builder requires​( Set<JavaModuleDescriptor.JavaRequires.JavaModifier> modifiers, String name )
{
JavaRequires requires = new JavaRequires( modifiers, name );
jModule.requires.add( requires );
jModule.requires.add( new JavaRequires( modifiers, name ) );
return this;
}

Expand All @@ -158,8 +172,7 @@ private Builder setAutomatic( boolean isAutomatic )
*/
public Builder requires( String name )
{
JavaRequires requires = new JavaRequires( name );
jModule.requires.add( requires );
jModule.requires.add( new JavaRequires( name ) );
return this;
}

Expand All @@ -171,8 +184,7 @@ public Builder requires( String name )
*/
public Builder exports( String source )
{
JavaExports exports = new JavaExports( source );
jModule.exports.add( exports );
jModule.exports.add( new JavaExports( source ) );
return this;
}

Expand All @@ -185,8 +197,25 @@ public Builder exports( String source )
*/
public Builder exports( String source, Set<String> targets )
{
JavaExports exports = new JavaExports( source, targets );
jModule.exports.add( exports );
jModule.exports.add( new JavaExports( source, targets ) );
return this;
}

/**
* Adds a service dependence.
*
* @param service The service type
* @return This Builder
*/
public Builder uses( String service )
{
jModule.uses.add( service );
return this;
}

public Builder provides​( String service, List<String> providers )
{
jModule.provides.add( new JavaProvides( service, providers ) );
return this;
}

Expand Down Expand Up @@ -349,4 +378,67 @@ public boolean equals( Object obj )
return true;
}
}

/**
* Represents Module.Provides
*
* @author Robert Scholte
* @since 1.0.0
*/
public static class JavaProvides
{
private final String service;

private final List<String> providers;

private JavaProvides( String service, List<String> providers )
{
this.service = service;
this.providers = providers;
}

public String service()
{
return service;
}

public List<String> providers()
{
return providers;
}

@Override
public int hashCode()
{
return Objects.hash( service, providers );
}

@Override
public boolean equals( Object obj )
{
if ( this == obj )
{
return true;
}
if ( obj == null )
{
return false;
}
if ( getClass() != obj.getClass() )
{
return false;
}

JavaProvides other = (JavaProvides) obj;
if ( !Objects.equals( service, other.service ) )
{
return false;
}
if ( !Objects.equals( providers, other.providers ) )
{
return false;
}
return true;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import javax.inject.Singleton;

import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor.JavaProvides;

/**
* Maps artifacts to modules and analyzes the type of required modules
Expand Down Expand Up @@ -114,7 +115,15 @@ public <T> ResolvePathsResult<T> resolvePaths( final ResolvePathsRequest<T> requ

result.setMainModuleDescriptor( mainModuleDescriptor );

Map<String, JavaModuleDescriptor> availableNamedModules = new HashMap<>();
// key = service, value = names of modules that provide this service
Map<String, Set<String>> availableProviders = new HashMap<>();

if( mainModuleDescriptor != null && request.isIncludeAllProviders() )
{
collectProviders( mainModuleDescriptor, availableProviders );
}

Map<String, JavaModuleDescriptor> availableNamedModules = new HashMap<>();

Map<String, ModuleNameSource> moduleNameSources = new HashMap<>();

Expand Down Expand Up @@ -163,6 +172,11 @@ public String extract( Path path )
moduleNameSources.put( moduleDescriptor.name(), source );

availableNamedModules.put( moduleDescriptor.name(), moduleDescriptor );

if ( request.isIncludeAllProviders() )
{
collectProviders( moduleDescriptor, availableProviders );
}
}

pathElements.put( t, moduleDescriptor );
Expand Down Expand Up @@ -196,12 +210,21 @@ public String extract( Path path )
if ( mainModuleDescriptor != null )
{
Set<String> requiredNamedModules = new HashSet<>();

requiredNamedModules.add( mainModuleDescriptor.name() );

requiredNamedModules.addAll( request.getAdditionalModules() );
selectRequires( mainModuleDescriptor,
Collections.unmodifiableMap( availableNamedModules ),
Collections.unmodifiableMap( availableProviders ),
requiredNamedModules );

select( mainModuleDescriptor, Collections.unmodifiableMap( availableNamedModules ), requiredNamedModules );
for ( String additionalModule : request.getAdditionalModules() )
{
selectModule( additionalModule,
Collections.unmodifiableMap( availableNamedModules ),
Collections.unmodifiableMap( availableProviders ),
requiredNamedModules );
}

// in case of identical module names, first one wins
Set<String> collectedModules = new HashSet<>( requiredNamedModules.size() );
Expand Down Expand Up @@ -258,8 +281,9 @@ else if ( descriptorPath.endsWith( "module-info.class" ) )
private ResolvePathResult resolvePath( Path path, ModuleNameExtractor fileModulenameExtractor ) throws IOException
{
ResolvePathResult result = new ResolvePathResult();

JavaModuleDescriptor moduleDescriptor = null;

// either jar or outputDirectory
if ( Files.isRegularFile( path ) || Files.exists( path.resolve( "module-info.class" ) ) )
{
Expand Down Expand Up @@ -293,23 +317,62 @@ private ResolvePathResult resolvePath( Path path, ModuleNameExtractor fileModule
moduleDescriptor = JavaModuleDescriptor.newAutomaticModule( moduleName ).build();
}
}

result.setModuleDescriptor( moduleDescriptor );

return result;
}

private void select( JavaModuleDescriptor module, Map<String, JavaModuleDescriptor> availableModules,
Set<String> namedModules )
private void selectRequires( JavaModuleDescriptor module,
Map<String, JavaModuleDescriptor> availableModules,
Map<String, Set<String>> availableProviders,
Set<String> namedModules )
{
for ( JavaModuleDescriptor.JavaRequires requires : module.requires() )
{
String requiresName = requires.name();
JavaModuleDescriptor requiredModule = availableModules.get( requiresName );
selectModule( requires.name(), availableModules, availableProviders, namedModules );
}

for ( String uses : module.uses() )
{
if ( availableProviders.containsKey( uses ) )
{
for ( String providerModule : availableProviders.get( uses ) )
{
JavaModuleDescriptor requiredModule = availableModules.get( providerModule );

if ( requiredModule != null && namedModules.add( providerModule ) )
{
selectRequires( requiredModule, availableModules, availableProviders, namedModules );
}
}
}
}
}

private void selectModule( String module, Map<String, JavaModuleDescriptor> availableModules, Map<String, Set<String>> availableProviders,
Set<String> namedModules )
{
JavaModuleDescriptor requiredModule = availableModules.get( module );

if ( requiredModule != null && namedModules.add( requiresName ) )
if ( requiredModule != null && namedModules.add( module ) )
{
selectRequires( requiredModule, availableModules, availableProviders, namedModules );
}
}

private void collectProviders( JavaModuleDescriptor moduleDescriptor, Map<String, Set<String>> availableProviders )
{
for ( JavaProvides provides : moduleDescriptor.provides() )
{
Set<String> providingModules = availableProviders.get( provides.service() );

if ( providingModules == null )
{
select( requiredModule, availableModules, namedModules );
providingModules = new HashSet<>();

availableProviders.put( provides.service(), providingModules );
}
providingModules.add( moduleDescriptor.name() );
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;

Expand All @@ -40,6 +41,8 @@ public abstract class ResolvePathsRequest<T>
private Collection<T> pathElements;

private Collection<String> additionalModules;

private boolean includeAllProviders;

private ResolvePathsRequest()
{
Expand All @@ -54,6 +57,11 @@ public static ResolvePathsRequest<File> withFiles( Collection<File> files )
return ofFiles( files );
}

public static ResolvePathsRequest<File> ofFiles( File... files )
{
return ofFiles( Arrays.asList( files ) );
}

public static ResolvePathsRequest<File> ofFiles( Collection<File> files )
{
ResolvePathsRequest<File> request = new ResolvePathsRequest<File>()
Expand All @@ -78,6 +86,11 @@ public static ResolvePathsRequest<Path> withPaths( Collection<Path> paths )
return ofPaths( paths );
}

public static ResolvePathsRequest<Path> ofPaths( Path... paths )
{
return ofPaths( Arrays.asList( paths ) );
}

public static ResolvePathsRequest<Path> ofPaths( Collection<Path> paths )
{
ResolvePathsRequest<Path> request = new ResolvePathsRequest<Path>() {
Expand All @@ -100,6 +113,11 @@ public static ResolvePathsRequest<String> withStrings( Collection<String> string
return ofStrings( strings );
}

public static ResolvePathsRequest<String> ofStrings( String... strings )
{
return ofStrings( Arrays.asList( strings ) );
}

public static ResolvePathsRequest<String> ofStrings( Collection<String> strings )
{
ResolvePathsRequest<String> request = new ResolvePathsRequest<String>() {
Expand Down Expand Up @@ -178,4 +196,21 @@ public Collection<String> getAdditionalModules()
}
return additionalModules;
}

/**
* Will also include all modules that contain providers for used services, should only be used at runtime (not during compile nor test)
*
* @param includeAllProviders
* @return this request
*/
public ResolvePathsRequest<T> setIncludeAllProviders( boolean includeAllProviders )
{
this.includeAllProviders = includeAllProviders;
return this;
}

public boolean isIncludeAllProviders()
{
return includeAllProviders;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ JavaModuleDescriptor parse( InputStream in ) throws IOException
}
}



return builder.build();
}
}
Loading

0 comments on commit 9115ce8

Please sign in to comment.