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; } }