Skip to main content

provenant/parsers/
mod.rs

1mod about;
2#[cfg(test)]
3mod about_scan_test;
4#[cfg(test)]
5mod about_test;
6mod alpine;
7#[cfg(test)]
8mod alpine_scan_test;
9mod arch;
10#[cfg(test)]
11mod arch_scan_test;
12#[cfg(test)]
13mod arch_test;
14mod autotools;
15#[cfg(test)]
16mod autotools_test;
17mod bazel;
18#[cfg(test)]
19mod bazel_module_test;
20#[cfg(test)]
21mod bazel_test;
22mod bower;
23#[cfg(test)]
24mod bower_scan_test;
25#[cfg(test)]
26mod bower_test;
27mod buck;
28#[cfg(test)]
29mod buck_test;
30mod bun_lock;
31#[cfg(test)]
32mod bun_lock_test;
33mod bun_lockb;
34#[cfg(test)]
35mod bun_lockb_test;
36mod cargo;
37mod cargo_lock;
38#[cfg(test)]
39mod cargo_lock_test;
40#[cfg(test)]
41mod cargo_scan_test;
42#[cfg(test)]
43mod cargo_test;
44mod chef;
45#[cfg(test)]
46mod chef_scan_test;
47#[cfg(test)]
48mod chef_test;
49mod clojure;
50#[cfg(test)]
51mod clojure_test;
52#[cfg(test)]
53mod cocoapods_scan_test;
54mod composer;
55#[cfg(test)]
56mod composer_scan_test;
57#[cfg(test)]
58mod composer_test;
59mod conan;
60mod conan_data;
61#[cfg(test)]
62mod conan_data_test;
63#[cfg(test)]
64mod conan_scan_test;
65#[cfg(test)]
66mod conan_test;
67mod conda;
68mod conda_meta_json;
69#[cfg(test)]
70mod conda_meta_json_test;
71#[cfg(test)]
72mod conda_scan_test;
73#[cfg(test)]
74mod conda_test;
75mod cpan;
76mod cpan_dist_ini;
77#[cfg(test)]
78mod cpan_dist_ini_test;
79mod cpan_makefile_pl;
80#[cfg(test)]
81mod cpan_makefile_pl_test;
82#[cfg(test)]
83mod cpan_scan_test;
84#[cfg(test)]
85mod cpan_test;
86mod cran;
87#[cfg(test)]
88mod cran_scan_test;
89#[cfg(test)]
90mod cran_test;
91mod dart;
92#[cfg(test)]
93mod dart_scan_test;
94#[cfg(test)]
95mod dart_test;
96mod debian;
97#[cfg(test)]
98mod debian_scan_test;
99#[cfg(test)]
100mod debian_test;
101mod deno;
102mod deno_lock;
103#[cfg(test)]
104mod deno_lock_test;
105#[cfg(test)]
106mod deno_scan_test;
107#[cfg(test)]
108mod deno_test;
109mod docker;
110#[cfg(test)]
111mod docker_scan_test;
112#[cfg(test)]
113mod docker_test;
114mod freebsd;
115#[cfg(test)]
116mod freebsd_scan_test;
117#[cfg(test)]
118mod freebsd_test;
119mod gitmodules;
120#[cfg(test)]
121mod gitmodules_scan_test;
122mod go;
123mod go_mod_graph;
124#[cfg(test)]
125mod go_scan_test;
126#[cfg(test)]
127mod go_test;
128#[cfg(test)]
129mod go_work_test;
130#[cfg(all(test, feature = "golden-tests"))]
131pub(crate) mod golden_test_utils;
132mod gradle;
133mod gradle_lock;
134#[cfg(test)]
135mod gradle_lock_test;
136mod gradle_module;
137#[cfg(test)]
138mod gradle_module_scan_test;
139#[cfg(test)]
140mod gradle_module_test;
141#[cfg(test)]
142mod gradle_scan_test;
143mod hackage;
144#[cfg(test)]
145mod hackage_scan_test;
146#[cfg(test)]
147mod hackage_test;
148mod haxe;
149#[cfg(test)]
150mod haxe_scan_test;
151#[cfg(test)]
152mod haxe_test;
153mod helm;
154#[cfg(test)]
155mod helm_scan_test;
156#[cfg(test)]
157mod helm_test;
158mod hex_lock;
159#[cfg(test)]
160mod hex_lock_test;
161mod license_normalization;
162mod maven;
163#[cfg(test)]
164mod maven_scan_test;
165#[cfg(test)]
166mod maven_test;
167mod meson;
168#[cfg(test)]
169mod meson_test;
170pub mod metadata;
171mod microsoft_update_manifest;
172#[cfg(test)]
173mod microsoft_update_manifest_test;
174mod misc;
175#[cfg(test)]
176mod misc_test;
177mod nix;
178#[cfg(test)]
179mod nix_scan_test;
180#[cfg(test)]
181mod nix_test;
182mod npm;
183mod npm_lock;
184#[cfg(test)]
185mod npm_lock_test;
186#[cfg(test)]
187mod npm_scan_test;
188#[cfg(test)]
189mod npm_test;
190mod npm_workspace;
191#[cfg(test)]
192mod npm_workspace_test;
193mod nuget;
194#[cfg(test)]
195mod nuget_scan_test;
196#[cfg(test)]
197mod nuget_test;
198mod opam;
199#[cfg(test)]
200mod opam_scan_test;
201mod os_release;
202#[cfg(test)]
203mod os_release_test;
204#[cfg(test)]
205mod osgi_test;
206mod pep508;
207mod pip_inspect_deplock;
208#[cfg(test)]
209mod pip_inspect_deplock_test;
210mod pipfile_lock;
211#[cfg(test)]
212mod pipfile_lock_test;
213mod pixi;
214#[cfg(test)]
215mod pixi_scan_test;
216#[cfg(test)]
217mod pixi_test;
218mod pnpm_lock;
219#[cfg(test)]
220mod pnpm_lock_test;
221mod podfile;
222mod podfile_lock;
223#[cfg(test)]
224mod podfile_lock_test;
225mod podspec;
226mod podspec_json;
227#[cfg(test)]
228mod podspec_json_test;
229mod poetry_lock;
230#[cfg(test)]
231mod poetry_lock_test;
232mod pylock_toml;
233#[cfg(test)]
234mod pylock_toml_test;
235mod python;
236#[cfg(test)]
237mod python_scan_test;
238#[cfg(test)]
239mod python_test;
240mod readme;
241#[cfg(test)]
242mod readme_test;
243mod requirements_txt;
244#[cfg(test)]
245mod requirements_txt_test;
246pub(crate) mod rfc822;
247mod rpm_db;
248#[cfg(test)]
249mod rpm_db_scan_test;
250mod rpm_license_files;
251#[cfg(test)]
252mod rpm_license_files_test;
253mod rpm_mariner_manifest;
254#[cfg(test)]
255mod rpm_mariner_manifest_test;
256mod rpm_parser;
257#[cfg(test)]
258mod rpm_scan_test;
259mod rpm_specfile;
260#[cfg(test)]
261mod rpm_specfile_test;
262mod rpm_yumdb;
263mod ruby;
264#[cfg(test)]
265mod ruby_scan_test;
266#[cfg(test)]
267mod ruby_test;
268mod sbt;
269#[cfg(test)]
270mod sbt_test;
271#[cfg(test)]
272mod scan_test_utils;
273mod swift_manifest_json;
274#[cfg(test)]
275mod swift_manifest_json_test;
276mod swift_resolved;
277#[cfg(test)]
278mod swift_resolved_test;
279#[cfg(test)]
280mod swift_scan_test;
281mod swift_show_dependencies;
282#[cfg(test)]
283mod swift_show_dependencies_test;
284pub mod utils;
285mod uv_lock;
286#[cfg(test)]
287mod uv_lock_test;
288mod vcpkg;
289#[cfg(test)]
290mod vcpkg_scan_test;
291#[cfg(test)]
292mod vcpkg_test;
293mod yarn_lock;
294#[cfg(test)]
295mod yarn_lock_test;
296
297#[cfg(all(test, feature = "golden-tests"))]
298mod golden_test;
299
300use std::cell::RefCell;
301use std::path::Path;
302
303use crate::models::{PackageData, PackageType};
304use crate::parsers::license_normalization::finalize_package_declared_license_references;
305
306thread_local! {
307    static PARSER_DIAGNOSTIC_STACK: RefCell<Vec<Vec<String>>> = const { RefCell::new(Vec::new()) };
308}
309
310#[derive(Debug, Default)]
311pub struct ParsePackagesResult {
312    pub packages: Vec<PackageData>,
313    pub scan_errors: Vec<String>,
314}
315
316pub(crate) fn capture_parser_diagnostics<F>(extract: F) -> ParsePackagesResult
317where
318    F: FnOnce() -> Vec<PackageData>,
319{
320    PARSER_DIAGNOSTIC_STACK.with(|stack| {
321        stack.borrow_mut().push(Vec::new());
322    });
323
324    let packages = extract()
325        .into_iter()
326        .map(|mut package| {
327            finalize_package_declared_license_references(&mut package);
328            package
329        })
330        .collect();
331    let scan_errors =
332        PARSER_DIAGNOSTIC_STACK.with(|stack| stack.borrow_mut().pop().unwrap_or_default());
333
334    ParsePackagesResult {
335        packages,
336        scan_errors,
337    }
338}
339
340pub(crate) fn record_parser_diagnostic(message: String) -> bool {
341    PARSER_DIAGNOSTIC_STACK.with(|stack| {
342        let mut stack = stack.borrow_mut();
343        let Some(active) = stack.last_mut() else {
344            return false;
345        };
346        active.push(message);
347        true
348    })
349}
350
351#[macro_export]
352macro_rules! parser_warn {
353    ($($arg:tt)*) => {{
354        let message = format!($($arg)*);
355        if !$crate::parsers::record_parser_diagnostic(message.clone()) {
356            log::warn!("{message}");
357        }
358    }};
359}
360
361/// Package parser trait for extracting metadata from package manifest files.
362///
363/// Each parser implementation handles a specific package manager/ecosystem
364/// (npm, Maven, Python, Cargo, etc.) and extracts standardized metadata into
365/// `PackageData` structures compatible with ScanCode Toolkit JSON output format.
366///
367/// # Implementation Guide
368///
369/// Implementors must provide:
370/// - `PACKAGE_TYPE`: Package URL (purl) type identifier (e.g., "npm", "pypi", "maven")
371/// - `is_match()`: Returns true if the given file path matches this parser's expected format
372/// - `extract_packages()`: Parses the file and returns all extracted package metadata
373///
374/// # Error Handling
375///
376/// Parsers should handle errors gracefully by returning default/empty `PackageData`
377/// and logging warnings with [`crate::parser_warn!`] rather than panicking. Scanner
378/// dispatch captures those warnings and attaches them to `FileInfo.scan_errors` so
379/// CI output and serialized scan results stay aligned.
380/// This allows the scan to continue processing other files even when individual
381/// files fail to parse.
382///
383/// # Example
384///
385/// ```ignore
386/// use provenant::models::{PackageData, PackageType};
387/// use provenant::parsers::PackageParser;
388/// use std::path::Path;
389///
390/// pub struct MyParser;
391///
392/// impl PackageParser for MyParser {
393///     const PACKAGE_TYPE: PackageType = PackageType::Npm;
394///
395///     fn is_match(path: &Path) -> bool {
396///         path.file_name().is_some_and(|name| name == "package.json")
397///     }
398///
399///     fn extract_packages(path: &Path) -> Vec<PackageData> {
400///         vec![PackageData::default()]
401///     }
402/// }
403/// ```
404pub trait PackageParser {
405    /// Package URL type identifier for this parser (e.g., PackageType::Npm, PackageType::Pypi).
406    const PACKAGE_TYPE: PackageType;
407
408    /// Extracts all packages from the given file path.
409    ///
410    /// Returns a vector of `PackageData` structures containing all extracted metadata
411    /// including name, version, dependencies, licenses, etc. Most parsers return a
412    /// single-element vector, but some (e.g., Bazel BUILD, Buck BUCK, Debian control)
413    /// can contain multiple packages in a single file.
414    ///
415    /// On parse errors, returns a vector with a default `PackageData` with minimal or
416    /// no fields populated.
417    fn extract_packages(path: &Path) -> Vec<PackageData>;
418
419    /// Checks if the given file path matches this parser's expected format.
420    ///
421    /// Returns true if the file should be handled by this parser based on filename,
422    /// extension, or path patterns. Used by the scanner to route files to appropriate parsers.
423    fn is_match(path: &Path) -> bool;
424
425    /// Returns the first package from [`extract_packages()`](Self::extract_packages),
426    /// or a default [`PackageData`] if the file contains no packages.
427    fn extract_first_package(path: &Path) -> PackageData {
428        Self::extract_packages(path)
429            .into_iter()
430            .map(|mut package| {
431                finalize_package_declared_license_references(&mut package);
432                package
433            })
434            .next()
435            .unwrap_or_default()
436    }
437}
438
439pub use self::about::AboutFileParser;
440pub use self::alpine::{AlpineApkParser, AlpineApkbuildParser, AlpineInstalledParser};
441pub use self::arch::{ArchPkginfoParser, ArchSrcinfoParser};
442pub use self::autotools::AutotoolsConfigureParser;
443pub use self::bazel::{BazelBuildParser, BazelModuleParser};
444pub use self::bower::BowerJsonParser;
445pub use self::buck::{BuckBuildParser, BuckMetadataBzlParser};
446pub use self::bun_lock::BunLockParser;
447pub use self::bun_lockb::BunLockbParser;
448pub use self::cargo::CargoParser;
449#[cfg_attr(not(test), allow(unused_imports))]
450pub use self::cargo_lock::CargoLockParser;
451pub use self::chef::{ChefMetadataJsonParser, ChefMetadataRbParser};
452pub use self::clojure::{ClojureDepsEdnParser, ClojureProjectCljParser};
453pub use self::composer::{ComposerJsonParser, ComposerLockParser};
454pub use self::conan::{ConanFilePyParser, ConanLockParser, ConanfileTxtParser};
455pub use self::conan_data::ConanDataParser;
456pub use self::conda::{CondaEnvironmentYmlParser, CondaMetaYamlParser};
457pub use self::conda_meta_json::CondaMetaJsonParser;
458pub use self::cpan::{CpanManifestParser, CpanMetaJsonParser, CpanMetaYmlParser};
459pub use self::cpan_dist_ini::CpanDistIniParser;
460pub use self::cpan_makefile_pl::CpanMakefilePlParser;
461pub use self::cran::CranParser;
462pub use self::dart::{PubspecLockParser, PubspecYamlParser};
463pub use self::debian::{
464    DebianControlInExtractedDebParser, DebianControlParser, DebianCopyrightParser, DebianDebParser,
465    DebianDebianTarParser, DebianDistrolessInstalledParser, DebianDscParser,
466    DebianInstalledListParser, DebianInstalledMd5sumsParser, DebianInstalledParser,
467    DebianMd5sumInPackageParser, DebianOrigTarParser,
468};
469pub use self::deno::DenoParser;
470pub use self::deno_lock::DenoLockParser;
471pub use self::docker::DockerfileParser;
472pub use self::freebsd::FreebsdCompactManifestParser;
473pub use self::gitmodules::GitmodulesParser;
474pub use self::go::{GoModParser, GoSumParser, GoWorkParser, GodepsParser};
475pub use self::go_mod_graph::GoModGraphParser;
476pub use self::gradle::GradleParser;
477pub use self::gradle_lock::GradleLockfileParser;
478pub use self::gradle_module::GradleModuleParser;
479pub use self::hackage::{HackageCabalParser, HackageCabalProjectParser, HackageStackYamlParser};
480pub use self::haxe::HaxeParser;
481pub use self::helm::{HelmChartLockParser, HelmChartYamlParser};
482pub use self::hex_lock::HexLockParser;
483pub use self::maven::MavenParser;
484pub use self::meson::MesonParser;
485pub use self::microsoft_update_manifest::MicrosoftUpdateManifestParser;
486pub use self::misc::{
487    AndroidApkRecognizer, AndroidLibraryRecognizer, AppleDmgRecognizer, Axis2MarRecognizer,
488    Axis2ModuleXmlRecognizer, CabArchiveRecognizer, ChromeCrxRecognizer, InstallShieldRecognizer,
489    IosIpaRecognizer, IsoImageRecognizer, IvyXmlRecognizer, JBossSarRecognizer,
490    JBossServiceXmlRecognizer, JavaEarAppXmlRecognizer, JavaEarRecognizer, JavaJarRecognizer,
491    JavaWarRecognizer, JavaWarWebXmlRecognizer, MeteorPackageRecognizer, MozillaXpiRecognizer,
492    NsisRecognizer, SharArchiveRecognizer, SquashfsRecognizer,
493};
494pub use self::nix::{NixDefaultParser, NixFlakeLockParser, NixFlakeParser};
495pub use self::npm::NpmParser;
496pub use self::npm_lock::NpmLockParser;
497pub use self::npm_workspace::NpmWorkspaceParser;
498pub use self::nuget::{
499    CentralPackageManagementPropsParser, DirectoryBuildPropsParser, DotNetDepsJsonParser,
500    NupkgParser, NuspecParser, PackageReferenceProjectParser, PackagesConfigParser,
501    PackagesLockParser, ProjectJsonParser, ProjectLockJsonParser,
502};
503pub use self::opam::OpamParser;
504pub use self::os_release::OsReleaseParser;
505pub use self::pip_inspect_deplock::PipInspectDeplockParser;
506pub use self::pipfile_lock::PipfileLockParser;
507pub use self::pixi::{PixiLockParser, PixiTomlParser};
508pub use self::pnpm_lock::PnpmLockParser;
509pub use self::podfile::PodfileParser;
510pub use self::podfile_lock::PodfileLockParser;
511pub use self::podspec::PodspecParser;
512pub use self::podspec_json::PodspecJsonParser;
513pub use self::poetry_lock::PoetryLockParser;
514pub use self::pylock_toml::PylockTomlParser;
515pub use self::python::PythonParser;
516pub use self::readme::ReadmeParser;
517pub use self::requirements_txt::RequirementsTxtParser;
518pub use self::rpm_db::{RpmBdbDatabaseParser, RpmNdbDatabaseParser, RpmSqliteDatabaseParser};
519pub use self::rpm_license_files::RpmLicenseFilesParser;
520pub use self::rpm_mariner_manifest::RpmMarinerManifestParser;
521pub use self::rpm_parser::RpmParser;
522pub use self::rpm_specfile::RpmSpecfileParser;
523pub use self::rpm_yumdb::RpmYumdbParser;
524pub use self::ruby::{
525    GemArchiveParser, GemMetadataExtractedParser, GemfileLockParser, GemfileParser, GemspecParser,
526};
527pub use self::sbt::SbtParser;
528pub use self::swift_manifest_json::SwiftManifestJsonParser;
529pub use self::swift_resolved::SwiftPackageResolvedParser;
530pub use self::swift_show_dependencies::SwiftShowDependenciesParser;
531pub use self::uv_lock::UvLockParser;
532pub use self::vcpkg::VcpkgManifestParser;
533pub use self::yarn_lock::YarnLockParser;
534
535/// Registers all parsers and recognizers, generating dispatch functions.
536///
537/// Parsers are tried first, then recognizers. This ordering is important because
538/// recognizers match broadly by file extension (e.g., `.jar`) and would shadow
539/// more specific parsers if checked first.
540macro_rules! register_package_handlers {
541    (
542        parsers: [$($parser:ty),* $(,)?],
543        recognizers: [$($recognizer:ty),* $(,)?] $(,)?
544    ) => {
545        pub fn try_parse_file(path: &Path) -> Option<ParsePackagesResult> {
546            $(
547                if <$parser>::is_match(path) {
548                    return Some(capture_parser_diagnostics(|| <$parser>::extract_packages(path)));
549                }
550            )*
551            $(
552                if <$recognizer>::is_match(path) {
553                    return Some(capture_parser_diagnostics(|| <$recognizer>::extract_packages(path)));
554                }
555            )*
556            None
557        }
558
559        // Used by the parser-golden maintenance tool in `xtask`.
560        // Scanner runtime dispatch goes through `try_parse_file()`.
561        #[allow(dead_code)]
562        pub fn parse_by_type_name(type_name: &str, path: &Path) -> Option<PackageData> {
563            match type_name {
564                $(
565                    stringify!($parser) => Some(<$parser>::extract_first_package(path)),
566                )*
567                $(
568                    stringify!($recognizer) => Some(<$recognizer>::extract_first_package(path)),
569                )*
570                _ => None
571            }
572        }
573
574        // Used by the parser-golden maintenance tool in `xtask` and by
575        // `tests/scanner_integration.rs` to verify parser registration.
576        #[allow(dead_code)]
577        pub fn list_parser_types() -> Vec<&'static str> {
578            vec![
579                $(
580                    stringify!($parser),
581                )*
582                $(
583                    stringify!($recognizer),
584                )*
585            ]
586        }
587    };
588}
589
590register_package_handlers! {
591    parsers: [
592        AboutFileParser,
593        AlpineApkParser,
594        AlpineApkbuildParser,
595        AlpineInstalledParser,
596        ArchPkginfoParser,
597        ArchSrcinfoParser,
598        AutotoolsConfigureParser,
599        BazelBuildParser,
600        BazelModuleParser,
601        BowerJsonParser,
602        BunLockParser,
603        BunLockbParser,
604        BuckBuildParser,
605        BuckMetadataBzlParser,
606        CargoLockParser,
607        CargoParser,
608        ChefMetadataJsonParser,
609        ChefMetadataRbParser,
610        ClojureDepsEdnParser,
611        ClojureProjectCljParser,
612        ComposerJsonParser,
613        ComposerLockParser,
614        ConanDataParser,
615        ConanFilePyParser,
616        ConanfileTxtParser,
617        ConanLockParser,
618        CondaEnvironmentYmlParser,
619        CondaMetaJsonParser,
620        CondaMetaYamlParser,
621        CpanDistIniParser,
622        CpanMakefilePlParser,
623        CpanManifestParser,
624        CpanMetaJsonParser,
625        CpanMetaYmlParser,
626        CranParser,
627        DebianControlInExtractedDebParser,
628        DebianControlParser,
629        DebianCopyrightParser,
630        DebianDebianTarParser,
631        DebianDebParser,
632        DebianDistrolessInstalledParser,
633        DebianDscParser,
634        DebianInstalledListParser,
635        DebianInstalledMd5sumsParser,
636        DebianInstalledParser,
637        DebianMd5sumInPackageParser,
638        DebianOrigTarParser,
639        DenoParser,
640        DenoLockParser,
641        DockerfileParser,
642        FreebsdCompactManifestParser,
643        GemArchiveParser,
644        GemfileLockParser,
645        GemfileParser,
646        GemMetadataExtractedParser,
647        GemspecParser,
648        GitmodulesParser,
649        GodepsParser,
650        GoModParser,
651        GoModGraphParser,
652        GoSumParser,
653        GoWorkParser,
654        GradleLockfileParser,
655        GradleParser,
656        GradleModuleParser,
657        HackageCabalParser,
658        HackageCabalProjectParser,
659        HackageStackYamlParser,
660        HelmChartYamlParser,
661        HelmChartLockParser,
662        HaxeParser,
663        HexLockParser,
664        MavenParser,
665        MesonParser,
666        MicrosoftUpdateManifestParser,
667        NixDefaultParser,
668        NixFlakeLockParser,
669        NixFlakeParser,
670        NpmLockParser,
671        NpmParser,
672        NpmWorkspaceParser,
673        DotNetDepsJsonParser,
674        CentralPackageManagementPropsParser,
675        DirectoryBuildPropsParser,
676        NupkgParser,
677        NuspecParser,
678        PackageReferenceProjectParser,
679        OpamParser,
680        OsReleaseParser,
681        PackagesConfigParser,
682        PackagesLockParser,
683        ProjectJsonParser,
684        ProjectLockJsonParser,
685        PipfileLockParser,
686        PipInspectDeplockParser,
687        PixiTomlParser,
688        PixiLockParser,
689        PnpmLockParser,
690        PodfileLockParser,
691        PodfileParser,
692        PodspecJsonParser,
693        PodspecParser,
694        PoetryLockParser,
695        PylockTomlParser,
696        PubspecLockParser,
697        PubspecYamlParser,
698        PythonParser,
699        UvLockParser,
700        VcpkgManifestParser,
701        ReadmeParser,
702        RequirementsTxtParser,
703        RpmBdbDatabaseParser,
704        RpmLicenseFilesParser,
705        RpmMarinerManifestParser,
706        RpmNdbDatabaseParser,
707        RpmParser,
708        RpmSpecfileParser,
709        RpmSqliteDatabaseParser,
710        RpmYumdbParser,
711        SbtParser,
712        SwiftManifestJsonParser,
713        SwiftPackageResolvedParser,
714        SwiftShowDependenciesParser,
715        YarnLockParser,
716    ],
717    recognizers: [
718        AndroidApkRecognizer,
719        AndroidLibraryRecognizer,
720        AppleDmgRecognizer,
721        Axis2MarRecognizer,
722        Axis2ModuleXmlRecognizer,
723        CabArchiveRecognizer,
724        ChromeCrxRecognizer,
725        InstallShieldRecognizer,
726        IosIpaRecognizer,
727        IsoImageRecognizer,
728        IvyXmlRecognizer,
729        JavaEarAppXmlRecognizer,
730        JavaEarRecognizer,
731        JavaJarRecognizer,
732        JavaWarRecognizer,
733        JavaWarWebXmlRecognizer,
734        JBossSarRecognizer,
735        JBossServiceXmlRecognizer,
736        MeteorPackageRecognizer,
737        MozillaXpiRecognizer,
738        NsisRecognizer,
739        SharArchiveRecognizer,
740        SquashfsRecognizer,
741    ],
742}