diff --git a/graph/api/src/main/java/org/jboss/windup/graph/model/LicenseModel.java b/graph/api/src/main/java/org/jboss/windup/graph/model/LicenseModel.java
new file mode 100644
index 0000000000..80dc023e1d
--- /dev/null
+++ b/graph/api/src/main/java/org/jboss/windup/graph/model/LicenseModel.java
@@ -0,0 +1,42 @@
+package org.jboss.windup.graph.model;
+
+import org.jboss.windup.graph.model.resource.FileModel;
+import org.jboss.windup.graph.model.resource.SourceFileModel;
+
+import com.tinkerpop.frames.Property;
+import com.tinkerpop.frames.modules.typedgraph.TypeValue;
+
+@TypeValue(LicenseModel.TYPE)
+public interface LicenseModel extends FileModel, SourceFileModel {
+
+ public static final String TYPE = "LicenseModel";
+ public static final String NAME = "licenseName";
+ public static final String URL = "licenseURL";
+
+ /**
+ * Indicates the license name.
+ */
+ @Property(NAME)
+ String getName();
+
+ /**
+ * Indicates the license name.
+ */
+ @Property(NAME)
+ void setName(String name);
+
+
+ /**
+ * Indicates the license url.
+ */
+ @Property(URL)
+ String getURL();
+
+
+ /**
+ * Indicates the license url.
+ */
+ @Property(NAME)
+ void setURL(String url);
+
+}
diff --git a/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/provider/DiscoverArchiveLicenseFilesRuleProvider.java b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/provider/DiscoverArchiveLicenseFilesRuleProvider.java
new file mode 100644
index 0000000000..8a6dbe5fb2
--- /dev/null
+++ b/rules-java/api/src/main/java/org/jboss/windup/rules/apps/java/scan/provider/DiscoverArchiveLicenseFilesRuleProvider.java
@@ -0,0 +1,171 @@
+package org.jboss.windup.rules.apps.java.scan.provider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.jboss.windup.config.GraphRewrite;
+import org.jboss.windup.config.metadata.MetadataBuilder;
+import org.jboss.windup.config.phase.ArchiveMetadataExtractionPhase;
+import org.jboss.windup.config.query.Query;
+import org.jboss.windup.config.ruleprovider.IteratingRuleProvider;
+import org.jboss.windup.graph.model.ArchiveModel;
+import org.jboss.windup.graph.model.LicenseModel;
+import org.jboss.windup.graph.model.resource.FileModel;
+import org.jboss.windup.graph.service.GraphService;
+import org.jboss.windup.reporting.model.TechnologyTagLevel;
+import org.jboss.windup.reporting.model.TechnologyTagModel;
+import org.jboss.windup.reporting.service.ClassificationService;
+import org.jboss.windup.reporting.service.TechnologyTagService;
+import org.ocpsoft.rewrite.config.ConditionBuilder;
+import org.ocpsoft.rewrite.context.EvaluationContext;
+
+/**
+ * Discovers Licenses files within archives.
+ *
+ * @author Brad Davis
+ *
+ */
+public class DiscoverArchiveLicenseFilesRuleProvider extends
+ IteratingRuleProvider {
+ private static final Logger LOG = Logger
+ .getLogger(DiscoverArchiveLicenseFilesRuleProvider.class
+ .getSimpleName());
+
+ private static final TechnologyTagLevel TECH_TAG_LEVEL = TechnologyTagLevel.INFORMATIONAL;
+
+ public DiscoverArchiveLicenseFilesRuleProvider() {
+ super(MetadataBuilder.forProvider(
+ DiscoverArchiveLicenseFilesRuleProvider.class).setPhase(
+ ArchiveMetadataExtractionPhase.class));
+ }
+
+ @Override
+ public String toStringPerform() {
+ return "DiscoverArchiveLicenseFiles";
+ }
+
+ @Override
+ public ConditionBuilder when() {
+ return Query.fromType(ArchiveModel.class);
+ }
+
+ @Override
+ public void perform(GraphRewrite event, EvaluationContext context,
+ ArchiveModel payload) {
+ List licenseFiles = findLicense(payload);
+ if (licenseFiles.size() == 0) {
+ // no licenses found, skip this one
+ return;
+ }
+
+ TechnologyTagService technologyTagService = new TechnologyTagService(
+ event.getGraphContext());
+ ClassificationService classificationService = new ClassificationService(
+ event.getGraphContext());
+ GraphService licenseService = new GraphService(
+ event.getGraphContext(), LicenseModel.class);
+
+ for (FileModel license : licenseFiles) {
+ LOG.info("Classifying: " + license.getFileName()
+ + " as License within archive: " + payload.getArchiveName());
+ classificationService.attachClassification(license, "License",
+ "License File.");
+
+ // http://opensource.org/licenses/
+ try (InputStream stream = license.asInputStream()) {
+ String content = IOUtils.toString(stream);
+
+ if (StringUtils.containsIgnoreCase(content,
+ "Apache License, Version 2.0")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "Apache License 2.0",
+ "http://www.apache.org/licenses/LICENSE-2.0",
+ "Apache License 2.0");
+ } else if (StringUtils.containsIgnoreCase(content,
+ "GNU General Public License")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "GNU General Public License",
+ "http://opensource.org/licenses/gpl-license",
+ "GNU License");
+ } else if (StringUtils.containsIgnoreCase(content,
+ "The MIT License (MIT)")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "MIT License",
+ "http://opensource.org/licenses/MIT", "MIT License");
+ } else if (StringUtils.containsIgnoreCase(content,
+ "Mozilla Public License, version 2.0")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "Mozilla Public License 2.0",
+ "http://opensource.org/licenses/MPL-2.0",
+ "Mozilla Public License 2.0");
+ } else if (StringUtils.containsIgnoreCase(content,
+ "GNU Lesser General Public License")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "GNU LGPL",
+ "http://opensource.org/licenses/lgpl-license",
+ "GNU LGPL");
+ } else if (StringUtils.containsIgnoreCase(content,
+ "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "CDDL", "http://opensource.org/licenses/CDDL-1.0",
+ "CDDL License");
+ } else if (StringUtils.containsIgnoreCase(content,
+ "Eclipse Public License")) {
+ tagLicense(licenseService, technologyTagService, license,
+ "Eclipse Public License",
+ "http://opensource.org/licenses/EPL-1.0",
+ "Eclipse Public License");
+ } else {
+ LOG.warning("Must be unknown license type: "
+ + license.getFileName());
+ tagLicense(licenseService, technologyTagService, license,
+ "Unknown License", "", "Unknown License");
+ }
+ } catch (IOException e) {
+ // should do something here...
+ }
+ }
+
+ }
+
+ private void tagLicense(GraphService licenseService,
+ TechnologyTagService technologyTagService, FileModel license,
+ String name, String url, String tagName) {
+ LOG.info("Identified: " + license.getFileName() + " as: " + name);
+
+ LicenseModel model = licenseService.addTypeToModel(license);
+ model.setName(name);
+ model.setURL(url);
+
+ // also add it as a tag.
+ technologyTagService
+ .addTagToFileModel(license, tagName, TECH_TAG_LEVEL);
+ }
+
+ private List findLicense(ArchiveModel archive) {
+ List licenses = new LinkedList<>();
+
+ Iterable files = archive.getContainedFileModels();
+ for (FileModel model : files) {
+ String fileName = model.getFileName();
+ fileName = StringUtils.lowerCase(fileName);
+
+ if (fileName.endsWith("license.txt")
+ || fileName.endsWith("license")
+ || fileName.endsWith("gpl.txt")
+ || fileName.endsWith("lgpl.txt")
+ || fileName.endsWith("notice.txt")
+ || fileName.endsWith("notice")) {
+ licenses.add(model);
+ }
+ }
+
+ return licenses;
+ }
+
+}