diff --git a/Readme.md b/Readme.md index 53ced36..eb3e876 100644 --- a/Readme.md +++ b/Readme.md @@ -6,7 +6,8 @@ This repository contains tooling for reading MPS models from command line - with ### Projects - A Gradle plugin for reading MPS files and building an object model - [here](mps-cli-gradle-plugin/Readme.md). - A Python library for reading MPS files and building an object model - [here](mps-cli-py/Readme.md). -- A Typescript libeary for reading MPS files and building an object model - [here](mps-cli-ts/Readme.md). +- A Typescript library for reading MPS files and building an object model - [here](mps-cli-ts/Readme.md). +- A Rust library for reading MPS files and building an object model - [here](mps-cli-rs/Readme.md). ### Repository Structure - `mps-cli-gradle-plugin` - the gradle plugin to read MPS models diff --git a/mps-cli-py/Readme.md b/mps-cli-py/Readme.md index 41d1072..cccd6a4 100644 --- a/mps-cli-py/Readme.md +++ b/mps-cli-py/Readme.md @@ -16,7 +16,7 @@ The core of the Python object model is given by the following classes: - `SRepository` - the repository containing the parsed model and meta-information ### Limitations -The plugin has currently the following limitations: +The library has currently the following limitations: - the recovered language information reflects only the used language in the loaded solutions ### Run tests diff --git a/mps-cli-rs/Cargo.lock b/mps-cli-rs/Cargo.lock index 44ef65a..3a21c1a 100644 --- a/mps-cli-rs/Cargo.lock +++ b/mps-cli-rs/Cargo.lock @@ -2,12 +2,421 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bzip2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" +dependencies = [ + "bzip2-sys", + "libc", +] + +[[package]] +name = "bzip2-sys" +version = "0.1.11+1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + +[[package]] +name = "cc" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +dependencies = [ + "jobserver", + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "deflate64" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive_arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "lockfree-object-pool" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lzma-rs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" +dependencies = [ + "byteorder", + "crc", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + [[package]] name = "mps-cli" version = "0.1.0" dependencies = [ "roxmltree", "walkdir", + "zip", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", ] [[package]] @@ -25,6 +434,117 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "serde" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.204" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "num-conv", + "powerfmt", + "serde", + "time-core", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" @@ -35,6 +555,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + [[package]] name = "winapi" version = "0.3.9" @@ -65,3 +591,94 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zip" +version = "2.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b895748a3ebcb69b9d38dcfdf21760859a4b0d0b0015277640c2ef4c69640e6f" +dependencies = [ + "aes", + "arbitrary", + "bzip2", + "constant_time_eq", + "crc32fast", + "crossbeam-utils", + "deflate64", + "displaydoc", + "flate2", + "hmac", + "indexmap", + "lzma-rs", + "memchr", + "pbkdf2", + "rand", + "sha1", + "thiserror", + "time", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zopfli" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" +dependencies = [ + "bumpalo", + "crc32fast", + "lockfree-object-pool", + "log", + "once_cell", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.12+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/mps-cli-rs/Cargo.toml b/mps-cli-rs/Cargo.toml index 7c8fc2f..b1ad443 100644 --- a/mps-cli-rs/Cargo.toml +++ b/mps-cli-rs/Cargo.toml @@ -16,7 +16,8 @@ std = [] [dependencies] walkdir = "2.5.0" roxmltree = "0.20.0" +zip = "2.1.5" [profile.release] lto = "fat" -codegen-units = 1 \ No newline at end of file +codegen-units = 1 diff --git a/mps-cli-rs/Readme.md b/mps-cli-rs/Readme.md new file mode 100644 index 0000000..0788f41 --- /dev/null +++ b/mps-cli-rs/Readme.md @@ -0,0 +1,25 @@ +## MPS CLI Rust Library + +This project provides a Rust library which parses MPS files and builds the object model. + +### Features +The following features are available: +- load MPS files (*.mpsr, *.mps, *.jar) and expose their content as Rust object model + - solutions, models, root nodes, nodes, children, references, properties +- extract the meta-information and expose it as Rust object model + - list of languages, their concepts with information about properties, references, children + +The core of the Rust object model is given by the following structures +- `SNode` - represents a node +- `SModel` - represents a model +- `SSolution` - represents a solution +- `SRepository` - the repository containing the parsed model and meta-information + +### Limitations +The library has currently the following limitations: +- the recovered language information reflects only the used language in the loaded solutions + +### Run tests + +- `cd mps-cli-rs` +- `cargo test` diff --git a/mps-cli-rs/src/builder/mod.rs b/mps-cli-rs/src/builder/mod.rs index 6699f3f..1fffceb 100644 --- a/mps-cli-rs/src/builder/mod.rs +++ b/mps-cli-rs/src/builder/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod smodules_repository_builder; +mod smodule_builder_from_jars; mod ssolution_builder; mod smodel_builder_base; mod smodel_builder_default_persistency; diff --git a/mps-cli-rs/src/builder/smodule_builder_from_jars.rs b/mps-cli-rs/src/builder/smodule_builder_from_jars.rs new file mode 100644 index 0000000..e67d239 --- /dev/null +++ b/mps-cli-rs/src/builder/smodule_builder_from_jars.rs @@ -0,0 +1,42 @@ +use std::env; +use std::fs::remove_dir_all; +use std::fs; +use std::{collections::HashMap, fs::File, io::Error, path::PathBuf}; +use zip::ZipArchive; + +use crate::builder::smodules_repository_builder::collect_modules_from_source; +use crate::model::{slanguage::SLanguage, ssolution::SSolution}; + +use super::slanguage_builder::SLanguageBuilder; +use super::smodel_builder_base::SModelBuilderCache; + + + +pub(crate) fn build_from_jars(dir : &String, jar_files : Vec, language_id_to_slanguage: &mut HashMap, language_builder : &mut SLanguageBuilder, model_builder_cache : &mut SModelBuilderCache) -> Result, Error> { + let mut res = Vec::new(); + let root_path = PathBuf::from(dir); + let root_path = fs::canonicalize(&root_path)?; + let temp_dir = env::temp_dir(); + println!("Collecting jars from root path: {}", root_path.display()); + for jar_file in jar_files { + let archive = File::open(jar_file.clone())?; + let mut archive = ZipArchive::new(archive)?; + if !archive.file_names().any(|it| it.ends_with(".msd")) { + continue; + } + + let mut absolute_path_to_jar_file = jar_file.canonicalize()?.into_os_string(); + absolute_path_to_jar_file.push("_jar"); + let absolute_path_to_jar_dir = PathBuf::from(absolute_path_to_jar_file.to_str().unwrap()); + let relative_directory_of_jar = absolute_path_to_jar_dir.strip_prefix(root_path.clone()).unwrap(); + let temporary_directory_to_extract_jar = temp_dir.join(relative_directory_of_jar); + + + println!(" - extracted '{}' to temporary dir '{}'", jar_file.file_name().unwrap().to_str().unwrap(), temporary_directory_to_extract_jar.to_str().unwrap()); + archive.extract(temporary_directory_to_extract_jar.clone())?; + collect_modules_from_source(&temporary_directory_to_extract_jar.to_str().unwrap().to_owned(), language_id_to_slanguage, language_builder, model_builder_cache, &mut res); + remove_dir_all(temporary_directory_to_extract_jar.clone())?; + println!(" - removed dir '{}'", temporary_directory_to_extract_jar.to_str().unwrap()); + }; + Ok(res) +} \ No newline at end of file diff --git a/mps-cli-rs/src/builder/smodules_repository_builder.rs b/mps-cli-rs/src/builder/smodules_repository_builder.rs index 78b20ad..12b8978 100644 --- a/mps-cli-rs/src/builder/smodules_repository_builder.rs +++ b/mps-cli-rs/src/builder/smodules_repository_builder.rs @@ -1,8 +1,11 @@ use std::collections::HashMap; +use std::fs::File; +use std::io::Error; use std::path::PathBuf; use std::time::Instant; use walkdir::WalkDir; +use zip::ZipArchive; use crate::builder::slanguage_builder::SLanguageBuilder; use crate::builder::smodel_builder_base::SModelBuilderCache; @@ -11,43 +14,59 @@ use crate::model::srepository::SRepository; use crate::model::ssolution::SSolution; use crate::model::slanguage::SLanguage; -pub(crate) fn build_repo_from_directory<'a>(source_dir: String) -> SRepository { +use super::smodule_builder_from_jars::build_from_jars; + +pub(crate) fn build_repo_from_directory<'a>(dir: String) -> SRepository { let mut all_solutions : Vec = Vec::new(); let mut language_builder = SLanguageBuilder::new(); let mut language_id_to_slanguage : HashMap = HashMap::new(); - build_solutions_from(source_dir, &mut language_id_to_slanguage, &mut language_builder, & mut all_solutions); + build_solutions_from(dir, &mut language_id_to_slanguage, &mut language_builder, & mut all_solutions); let all_languages = language_id_to_slanguage.into_iter().map(|(_k, lan)| lan).collect(); SRepository::new(all_solutions, all_languages) } -fn build_solutions_from<'a>(source_dir: String, language_id_to_slanguage: &'a mut HashMap, language_builder : &mut SLanguageBuilder, solutions : &'a mut Vec) { +fn build_solutions_from<'a>(dir: String, language_id_to_slanguage: &'a mut HashMap, language_builder : &mut SLanguageBuilder, solutions : &'a mut Vec) { let now = Instant::now(); - collect_modules_from_sources(source_dir.clone(), language_id_to_slanguage, language_builder, solutions); + collect_modules(dir.clone(), language_id_to_slanguage, language_builder, solutions); let elapsed = now.elapsed(); - println!("{} milli seconds for handling {}", elapsed.as_millis(), source_dir); + println!("{} milli seconds for handling {}", elapsed.as_millis(), dir); } -fn collect_modules_from_sources<'a>(source_dir: String, language_id_to_slanguage: &'a mut HashMap, language_builder : &mut SLanguageBuilder, solutions : &'a mut Vec) { +fn collect_modules<'a>(dir: String, language_id_to_slanguage: &'a mut HashMap, language_builder : &mut SLanguageBuilder, solutions : &'a mut Vec) { let mut model_builder_cache = SModelBuilderCache::new(); - let msd_files = find_msd_files(&source_dir, 3); + collect_modules_from_source(&dir, language_id_to_slanguage, language_builder, &mut model_builder_cache, solutions); + collect_modules_from_jars(dir, language_id_to_slanguage, language_builder, &mut model_builder_cache, solutions); +} + +pub(crate) fn collect_modules_from_source(dir: &String, language_id_to_slanguage: &mut HashMap, language_builder: &mut SLanguageBuilder, model_builder_cache : &mut SModelBuilderCache, solutions: &mut Vec) { + let msd_files = find_files_with_extension(dir, "msd"); msd_files.iter() .for_each(|msd_file| { - let s = build_solution(msd_file, language_id_to_slanguage, language_builder, &mut model_builder_cache); + let s = build_solution(msd_file, language_id_to_slanguage, language_builder, model_builder_cache); solutions.push(s); }); } -fn find_msd_files(source_dir: &String, start_depth: usize) -> Vec { - let walk_dir: WalkDir = WalkDir::new(source_dir).max_depth(start_depth); +fn collect_modules_from_jars(dir: String, language_id_to_slanguage: &mut HashMap, language_builder: &mut SLanguageBuilder, model_builder_cache : &mut SModelBuilderCache, solutions: &mut Vec) { + let jar_files = find_files_with_extension(&dir, "jar"); + let res = build_from_jars(&dir, jar_files, language_id_to_slanguage, language_builder, model_builder_cache); + match res { + Ok(mut s) => solutions.append(&mut s), + Err(err) => println!("error {}", err), + } +} + +fn find_files_with_extension(source_dir: &String, searched_ext : &str) -> Vec { + let walk_dir: WalkDir = WalkDir::new(source_dir); let mut msd_files = Vec::new(); for entry in walk_dir.into_iter() { let dir_entry = entry.unwrap(); let path_buf = dir_entry.into_path(); if let Some(ext) = path_buf.extension() { - if ext == "msd" { + if ext == searched_ext { msd_files.push(path_buf) } } @@ -61,7 +80,7 @@ mod tests { use std::cell::RefCell; use std::rc::Rc; - use crate::builder::smodules_repository_builder::{build_repo_from_directory, find_msd_files}; + use crate::builder::smodules_repository_builder::{build_repo_from_directory, find_files_with_extension}; use crate::model::smodel::SModel; #[test] @@ -69,7 +88,7 @@ mod tests { //given let src_dir = "../mps_test_projects/mps_cli_lanuse_file_per_root/".to_string(); //when - let msd_files = find_msd_files(&src_dir, 3); + let msd_files = find_files_with_extension(&src_dir, "msd"); //then assert_eq!(msd_files.len(), 2); diff --git a/mps-cli-rs/tests/jars_persistency_tests.rs b/mps-cli-rs/tests/jars_persistency_tests.rs new file mode 100644 index 0000000..e6bc2d9 --- /dev/null +++ b/mps-cli-rs/tests/jars_persistency_tests.rs @@ -0,0 +1,9 @@ +mod model_completeness_tests; +use mps_cli::build_repo_from_directory; + +#[test] +fn test_build_repository() { + let path = "../mps_test_projects/mps_cli_lanuse_binary/"; + let repo = build_repo_from_directory(path.to_string()); + model_completeness_tests::check_model_completeness(&repo, "mps.cli.lanuse.library_top", "mps.cli.lanuse.library_second"); +} \ No newline at end of file diff --git a/mps_test_projects/mps_cli_lanuse_binary/mps_cli_lanuse_file_per_root.jar b/mps_test_projects/mps_cli_lanuse_binary/mps_cli_lanuse_file_per_root.jar index 8fc86ac..98f046b 100644 Binary files a/mps_test_projects/mps_cli_lanuse_binary/mps_cli_lanuse_file_per_root.jar and b/mps_test_projects/mps_cli_lanuse_binary/mps_cli_lanuse_file_per_root.jar differ