package org.jboss.windup.rules.apps.java.scan.provider;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.commons.lang3.StringUtils;
import org.jboss.windup.config.AbstractRuleProvider;
import org.jboss.windup.config.GraphRewrite;
import org.jboss.windup.config.loader.RuleLoaderContext;
import org.jboss.windup.config.metadata.RuleMetadata;
import org.jboss.windup.config.operation.iteration.AbstractIterationOperation;
import org.jboss.windup.config.phase.ClassifyFileTypesPhase;
import org.jboss.windup.config.query.Query;
import org.jboss.windup.graph.model.ArchiveModel;
import org.jboss.windup.graph.service.OrganizationService;
import org.jboss.windup.rules.apps.java.scan.operation.packagemapping.PackageNameMapping;
import org.jboss.windup.util.Logging;
import org.ocpsoft.rewrite.config.Configuration;
import org.ocpsoft.rewrite.config.ConfigurationBuilder;
import org.ocpsoft.rewrite.context.EvaluationContext;
/**
* Look at the package structure of the archive. If the packages all start with known organization's package structure, then mark as potential organization.
*
* @author <a href="mailto:bradsdavis@gmail.com">Brad Davis</a>
*/
@RuleMetadata(phase = ClassifyFileTypesPhase.class)
public class DiscoverOrganizationByPackageStructureProvider extends AbstractRuleProvider
{
private static final Logger LOG = Logging.get(DiscoverOrganizationByPackageStructureProvider.class);
// @formatter:off
@Override
public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext)
{
return ConfigurationBuilder.begin()
.addRule()
.when(Query.fromType(ArchiveModel.class))
.perform(
new AbstractIterationOperation<ArchiveModel>() {
public void perform(GraphRewrite event, EvaluationContext context, ArchiveModel payload) {
final OrganizationService organizationService = new OrganizationService(event.getGraphContext());
LOG.info("Processing Archive: "+payload.getArchiveName());
Set<String> packageSet = new HashSet<>();
Set<String> possibleOrganization = new HashSet<>();
File archiveFile = payload.asFile();
try(ZipFile zipFile = new ZipFile(archiveFile)) {
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while(entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
if(!entry.isDirectory()) {
if(StringUtils.endsWith(entry.getName(), ".class")) {
String pkg = findPackage(payload, entry.getName());
packageSet.add(pkg);
}
}
}
for(String pkg : packageSet) {
String organization = findOrganization(event, pkg);
if(organization != null) {
possibleOrganization.add(organization);
}
}
}
catch(IOException e) {
LOG.warning("Error loading archive: "+payload.getFileName());
}
if(possibleOrganization.isEmpty()) {
LOG.info(" -- Archive: "+payload.getArchiveName()+" organization unknown.");
organizationService.attachOrganization(payload, "Unknown");
}
else if(possibleOrganization.size() > 1) {
LOG.warning(" -- Archive: "+payload.getArchiveName()+" has more than one organization: ");
for(String organization : possibleOrganization) {
//attach the organization to the archive.
organizationService.attachOrganization(payload, organization);
LOG.warning(" -- "+organization);
}
}
else {
organizationService.attachOrganization(payload, possibleOrganization.iterator().next());
LOG.info(" -- Archive: "+payload.getFileName()+" has organization: "+possibleOrganization.iterator().next());
}
}
}
);
}
// @formatter:on
private String findOrganization(GraphRewrite context, String pkg)
{
return PackageNameMapping.getOrganizationForPackage(context, pkg);
};
private String findPackage(final ArchiveModel payload, String entryName) {
String packageName = StringUtils.removeEnd(entryName, ".class");
packageName = StringUtils.replace(packageName, "/", ".");
packageName = StringUtils.substringBeforeLast(packageName, ".");
if(StringUtils.endsWith(payload.getArchiveName(), ".war")) {
packageName = StringUtils.substringAfterLast(packageName, "WEB-INF.classes.");
}
else if(StringUtils.endsWith(payload.getArchiveName(), ".par")) {
packageName = StringUtils.removeStart(packageName, "classes.");
}
return packageName;
}
}