blob: afb96b6c8730f6918a8c630088cdc928351420ee [file] [log] [blame]
package org.apache.maven.plugin.compiler.module;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import org.apache.maven.plugin.compiler.module.ProjectAnalyzerResult.ModuleNameSource;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.logging.AbstractLogEnabled;
/**
* Maps artifacts to modules and analyzes the type of required modules
*
* @author Robert Scholte
* @since 3.7.0
*/
@Component( role = ProjectAnalyzer.class )
public class ProjectAnalyzer extends AbstractLogEnabled
{
@Requirement( hint = "asm" )
private ModuleInfoParser asmParser;
@Requirement( hint = "reflect" )
private ModuleInfoParser reflectParser;
public ProjectAnalyzerResult analyze( ProjectAnalyzerRequest request )
throws IOException
{
ProjectAnalyzerResult result = new ProjectAnalyzerResult();
Map<File, JavaModuleDescriptor> pathElements =
new LinkedHashMap<File, JavaModuleDescriptor>( request.getDependencyArtifacts().size() );
JavaModuleDescriptor baseModuleDescriptor = request.getBaseModuleDescriptor();
Map<String, JavaModuleDescriptor> availableNamedModules = new HashMap<String, JavaModuleDescriptor>();
Map<String, ModuleNameSource> moduleNameSources = new HashMap<String, ModuleNameSource>();
// start from root
result.setBaseModuleDescriptor( baseModuleDescriptor );
// collect all modules from path
for ( File file : request.getDependencyArtifacts() )
{
JavaModuleDescriptor descriptor = extractDescriptor( file );
if ( descriptor != null )
{
availableNamedModules.put( descriptor.name(), descriptor );
}
if ( descriptor == null || descriptor.isAutomatic() )
{
Manifest manifest = extractManifest( file );
String modulename = null;
if ( manifest != null )
{
modulename = manifest.getMainAttributes().getValue( "Automatic-Module-Name" );
}
if ( modulename != null )
{
moduleNameSources.put( modulename, ModuleNameSource.MANIFEST );
}
else if ( descriptor != null )
{
moduleNameSources.put( descriptor.name(), ModuleNameSource.FILENAME );
}
}
else
{
moduleNameSources.put( descriptor.name(), ModuleNameSource.MODULEDESCRIPTOR );
}
pathElements.put( file, descriptor );
}
result.setPathElements( pathElements );
result.setModuleNameSources( moduleNameSources );
if ( baseModuleDescriptor != null )
{
Set<String> requiredNamedModules = new HashSet<String>();
Set<String> requiredUnnamedModules = new HashSet<String>();
select( baseModuleDescriptor, Collections.unmodifiableMap( availableNamedModules ), requiredNamedModules,
requiredUnnamedModules );
result.setRequiredNormalModules( requiredNamedModules );
result.setRequiredAutomaticModules( requiredUnnamedModules );
}
return result;
}
private JavaModuleDescriptor extractDescriptor( File file )
throws IOException
{
JavaModuleDescriptor moduleDescriptor;
if ( file.isFile() || new File( file, "module-info.class" ).exists() )
{
moduleDescriptor = reflectParser.getModuleDescriptor( file );
if ( moduleDescriptor == null )
{
moduleDescriptor = asmParser.getModuleDescriptor( file );
}
}
else
{
moduleDescriptor = null;
}
return moduleDescriptor;
}
private Manifest extractManifest( File file )
throws IOException
{
Manifest manifest;
if ( file.isFile() )
{
JarFile jarFile = null;
try
{
jarFile = new JarFile( file );
manifest = jarFile.getManifest();
}
finally
{
jarFile.close();
}
}
else if ( new File( file, "META-INF/MANIFEST.MF" ).exists() )
{
manifest = new Manifest( new FileInputStream( new File( file, "META-INF/MANIFEST.MF" ) ) );
}
else
{
manifest = null;
}
return manifest;
}
private void select( JavaModuleDescriptor module, Map<String, JavaModuleDescriptor> availableModules,
Set<String> namedModules, Set<String> unnamedModules )
{
for ( JavaModuleDescriptor.JavaRequires requires : module.requires() )
{
String requiresName = requires.name();
JavaModuleDescriptor requiredModule = availableModules.get( requiresName );
if ( requiredModule != null && !requiredModule.isAutomatic() )
{
if ( namedModules.add( requiresName ) )
{
select( requiredModule, availableModules, namedModules, unnamedModules );
}
}
else
{
unnamedModules.add( requiresName );
}
}
}
}