Compare commits
931 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d50e49ad37 | |||
| c8dc10f2e3 | |||
| 0504663814 | |||
| 62611a7255 | |||
| 407cd0ca60 | |||
| b384f1b0c3 | |||
| 14c4e9dda7 | |||
| 12fb549469 | |||
| 2599fdb1d2 | |||
| d05395075d | |||
| 664ecd6bb7 | |||
| 6b639e940c | |||
| 5b688d42ba | |||
| 3124ea4e67 | |||
| e9afa78444 | |||
| ef6fd54af3 | |||
| 03f68cefb7 | |||
| f8fa7df3f3 | |||
| 25cfe0193c | |||
| 3612780d15 | |||
| 7d8247047b | |||
| 91a1955454 | |||
| 1f3c396c5b | |||
| b9dd0ab1a9 | |||
| 779dd26527 | |||
| 65969e22a0 | |||
| 23f7a4e53f | |||
| 5b1ed8bef5 | |||
| 583ae2df11 | |||
| 14cd1e7a76 | |||
| 4572b55f98 | |||
| af2dbc7cd9 | |||
| 5d7ba5c842 | |||
| bee59e39a0 | |||
| 8d24ac3651 | |||
| 7beb21ad66 | |||
| ed51dbaf85 | |||
| 488ba05eda | |||
| 5dac5ed88b | |||
| 4bb89c1827 | |||
| 647c7a6ce0 | |||
| 6d5a8c0db7 | |||
| 3314ab026b | |||
| 8b612a1047 | |||
| 28ecf79643 | |||
| 8f78ba8b97 | |||
| 94b0870a53 | |||
| b9ff056b61 | |||
| 7e1a11373b | |||
| 200625aa3a | |||
| f1e52c5ad8 | |||
| 1217e64532 | |||
| c454d022dc | |||
| c4b8dcd88b | |||
| 3a62fb5900 | |||
| d127856726 | |||
| 02e9866398 | |||
| ed8c9daa8a | |||
| 59ec709c69 | |||
| 68fa22ba9b | |||
| e8b2f3cd0b | |||
| 74eb69534d | |||
| 710bc7ed7c | |||
| be17a6e186 | |||
| b7eb6303ec | |||
| 4d012ee1e1 | |||
| e3a73465f7 | |||
| 6b5057b870 | |||
| e577648efd | |||
| b3664d2391 | |||
| 3dc4059036 | |||
| 6d6b2f72b6 | |||
| a542cf56d4 | |||
| 1fdb813d1d | |||
| 6c3b63cf55 | |||
| 6b195587c1 | |||
| d323b3c5c9 | |||
| b03d7884bb | |||
| 37e6e61eff | |||
| 42e5b4e867 | |||
| fc8c92e922 | |||
| 5d7cbd3477 | |||
| 42b689867e | |||
| d4fb28607d | |||
| dfbdf99bbc | |||
| 7848ea5ec0 | |||
| 62afc06f56 | |||
| dbe2257b47 | |||
| 2029bef6eb | |||
| ffddb8faa0 | |||
| 456c89a5d5 | |||
| 37986f0ed5 | |||
| b883c7cb11 | |||
| 23a7e515f8 | |||
| 05e17e1c7f | |||
| 829942dcf9 | |||
| 9ce1ea66dc | |||
| d6d611d381 | |||
| 7020e948b8 | |||
| b96511d9d4 | |||
| ed5ca49755 | |||
| c1352e2ad6 | |||
| 1a6988c2ea | |||
| 0cca63e646 | |||
| 05aa2aeb75 | |||
| e3cc107bfa | |||
| 4a59c27793 | |||
| abde63ebee | |||
| 346fb471da | |||
| d4c5a1ee1c | |||
| e3598b99a5 | |||
| ab32732f26 | |||
| 3949cfa736 | |||
| 406d172169 | |||
| b550b9f9d1 | |||
| 211268f210 | |||
| 348a3e6692 | |||
| c3c63ce0e3 | |||
| 20d8656237 | |||
| e114cbeeaf | |||
| a6a6edb9f2 | |||
| 5cfb4f5122 | |||
| eec11c8e5f | |||
| 438dedd1ab | |||
| a950acbaba | |||
| f44875d072 | |||
| d7360e7a41 | |||
| add2f57397 | |||
| cd3c17d73f | |||
| fe6d783222 | |||
| fc8b0f1822 | |||
| bd56117c80 | |||
| 6102c970c8 | |||
| 29903058a9 | |||
| b3940dea1b | |||
| 3dac630d05 | |||
| 10108d75b8 | |||
| 24cb64579b | |||
| 86239cc777 | |||
| 685aea1728 | |||
| 8ea99b9463 | |||
| bc20a48570 | |||
| a17865683c | |||
| 6f76ee384c | |||
| eb4e041682 | |||
| 477aa754b3 | |||
| 48bff0aa6c | |||
| 4ea9fec9e2 | |||
| 5167ba7aee | |||
| f3a965841b | |||
| 08ddb5f4c4 | |||
| 4ec63ffd0d | |||
| 4cb3e82972 | |||
| 0a20741f39 | |||
| 4575748f16 | |||
| 028ee831b8 | |||
| 3595dd3339 | |||
| 54981cd57c | |||
| 0aab8cacaa | |||
| 15b4d33e00 | |||
| 367ba5cddf | |||
| ff64efbcdf | |||
| 5bc0c499d8 | |||
| f667318b58 | |||
| 87c9d15ad5 | |||
| 127736d188 | |||
| 139ab8d4df | |||
| 4abb8035b8 | |||
| 0ca1807d64 | |||
| 5ae90d201c | |||
| 6c416009d7 | |||
| 50da9bcb50 | |||
| 9e6a2d8a7c | |||
| cfb84cae44 | |||
| 4239833713 | |||
| 4fa1a3948e | |||
| 1b78e854f0 | |||
| c62a2362d2 | |||
| eb1855fcb7 | |||
| d4863239cd | |||
| 4b7ddb9c15 | |||
| e5bb35b335 | |||
| 7eabd09b3a | |||
| 087f0c0ede | |||
| db9d6d9109 | |||
| 700e180522 | |||
| 8584997f5f | |||
| 4710b3b641 | |||
| 227e2489c1 | |||
| 91a5b19378 | |||
| 4c20441c4e | |||
| edfe1e6d54 | |||
| 7869f77704 | |||
| 34fd405bca | |||
| f03ee9f908 | |||
| b053638204 | |||
| d790194682 | |||
| 3fec2b9756 | |||
| bc7a31d791 | |||
| 05d84c6673 | |||
| f6645e3928 | |||
| 50b00b12b0 | |||
| 569371ffff | |||
| f7b72b225a | |||
| d1bed54cf1 | |||
| ba868887d4 | |||
| 3a7853dcbe | |||
| 60af7deacd | |||
| 49bc3151b0 | |||
| d6b7bae38a | |||
| 715cc22722 | |||
| 88b23e09b6 | |||
| 4697f2ecad | |||
| 612484c0b6 | |||
| 0e4974babe | |||
| 5fdd7d8bd6 | |||
| b5c87ccfb7 | |||
| 2efe6ae7a4 | |||
| 5775984730 | |||
| cbab70fd7c | |||
| cfa2a30006 | |||
| 09a3b0d155 | |||
| ca9cd77ded | |||
| 812601217a | |||
| 3a6ec5ef0c | |||
| 4197a7654f | |||
| 3133014650 | |||
| 4bce945946 | |||
| 2d15c9c01c | |||
| 58e648828b | |||
| d87b268a40 | |||
| 5174645059 | |||
| e4286bc35b | |||
| cf4d13da31 | |||
| a89b064e29 | |||
| 1e41973eb5 | |||
| b4e496fceb | |||
| bb94fc7d71 | |||
| 959378c456 | |||
| 787e128d5c | |||
| b7912a7be7 | |||
| 0bc7aa6ba7 | |||
| 367da39bbb | |||
| 6d8ffb903f | |||
| 0e992f897f | |||
| 3f19878c18 | |||
| 308f64a7e2 | |||
| 1eab92b299 | |||
| 7a8b8f138f | |||
| 926ea54c39 | |||
| b44494a093 | |||
| a6094a82cb | |||
| 07f58d191b | |||
| 51eae92a5a | |||
| 0be3f3fb76 | |||
| 9f000eb90c | |||
| b7926bfa19 | |||
| fa76ffa5ca | |||
| 5ed8ade862 | |||
| 7a31ce16e2 | |||
| 16c9ca9e4b | |||
| 00c13b9939 | |||
| dbced8bef7 | |||
| 9552922795 | |||
| de53c8886b | |||
| 3672d13215 | |||
| 5ab036e9d3 | |||
| accf52ca38 | |||
| 51d14a7a01 | |||
| db0defb93f | |||
| 1fca0d22bf | |||
| 7d7e92432e | |||
| 86ad3f6b05 | |||
| 615ab564e5 | |||
| ee36a46d51 | |||
| 293568228c | |||
| 8b86276011 | |||
| 9406675bf2 | |||
| aa08a4ca37 | |||
| abf8777b0a | |||
| a6a2b02cd8 | |||
| 445dff7c5e | |||
| 37076fa4eb | |||
| 8c871a6172 | |||
| 3e42358f2a | |||
| 9bdb91b3c0 | |||
| 7f1f090a10 | |||
| 5c91c204fa | |||
| 11c7955b1e | |||
| 72d4457a24 | |||
| 9606cab81e | |||
| 7cd47114e0 | |||
| cd578b7b19 | |||
| f3d9b4a9f3 | |||
| b0fb892b16 | |||
| 66ca4e48bb | |||
| 96cd4daca5 | |||
| a1f08ad1b4 | |||
| 44c3140b20 | |||
| 7fac2b811b | |||
| 201512d5f2 | |||
| c1f5d8392d | |||
| 1aaeb75e0e | |||
| 0bbe1c6cdc | |||
| b78f75775d | |||
| 34f44b02a2 | |||
| 93c1321b99 | |||
| 73cb9ab3e5 | |||
| e402768212 | |||
| 6095f0233e | |||
| 9b1f4ecff9 | |||
| 3c884b583e | |||
| ea653cbd18 | |||
| b2679f3f17 | |||
| 231a7fa7c4 | |||
| a3936d69cb | |||
| a273584cc8 | |||
| 62c4e404b3 | |||
| d1b6b5c76f | |||
| b5cf3e9f59 | |||
| d97c772c70 | |||
| d5460068d4 | |||
| 5ac34a700f | |||
| a40762f09d | |||
| 0f00eaed78 | |||
| 01653f60f9 | |||
| d8b6f1fef1 | |||
| 1ecd0af268 | |||
| c2dc896fce | |||
| 2f714d0b3e | |||
| 0bbcaca067 | |||
| 55d3d8437a | |||
| 9e2ab8507f | |||
| 6ee6c77d6e | |||
| 9b5d4e5b08 | |||
| 49f8b530b7 | |||
| 56176d0e36 | |||
| ab41c900da | |||
| 92e0e5e570 | |||
| 90645e5e85 | |||
| 872c345ac9 | |||
| b4e0ddb7ad | |||
| a1f40a3e6e | |||
| 28df1af226 | |||
| 195953d63c | |||
| a93684f1f2 | |||
| 18e8f09654 | |||
| 85ebcadcdd | |||
| 0efeba3744 | |||
| 2a63519e8c | |||
| ba1d546579 | |||
| 8baaae4da6 | |||
| ed05a3223f | |||
| 25e3134e35 | |||
| f1b9b98f5d | |||
| d2f7eda074 | |||
| a5d5809385 | |||
| d9d38b9cc1 | |||
| 1e147f97e1 | |||
| db0cfad6b9 | |||
| 3062eedb4f | |||
| 1e3dd4c5cd | |||
| a7871abbd9 | |||
| effa632fab | |||
| 161f2eda86 | |||
| bf3a08cf85 | |||
| 7bc208e490 | |||
| a4dbc33b9a | |||
| 6b2e042e76 | |||
| b4bb15c66f | |||
| 7bf28a20e7 | |||
| d386c069ee | |||
| d83fdb48c9 | |||
| 6aa633c8c5 | |||
| eddd643249 | |||
| 9be2f99e7b | |||
| 2d5bfc0fe2 | |||
| c01f864e37 | |||
| a8be796d68 | |||
| 4acbdbe896 | |||
| 34a9eef8b8 | |||
| 0f56fa4baa | |||
| 82a8404b2e | |||
| bce8affe16 | |||
| 4bbd8097a2 | |||
| da9c810d78 | |||
| 431d066300 | |||
| 6d50bd891a | |||
| 1d00e3c5d8 | |||
| 97533e7c3d | |||
| e69422c8d8 | |||
| a277ac2fe4 | |||
| 1067b1e245 | |||
| 7987f13a11 | |||
| ccda1bdd73 | |||
| 76a6f2d2d0 | |||
| 69428b2281 | |||
| 7cd39918a0 | |||
| 9a626c9da6 | |||
| 0520797c09 | |||
| 9b85ba5b90 | |||
| 993a5bbc92 | |||
| ca738979ce | |||
| c9489bb912 | |||
| fce688f47f | |||
| 8cfb56adf4 | |||
| 6833c195c1 | |||
| 053346d79b | |||
| 044c9c95f8 | |||
| b23ea69b3e | |||
| 46f9c5ff05 | |||
| 3bc4b50d74 | |||
| 1a2849dfb0 | |||
| bcb5883230 | |||
| 18080c1cfb | |||
| 2600a3887e | |||
| 45bec2a67d | |||
| da7456fd2a | |||
| 275ba00e24 | |||
| d00bf4649d | |||
| 04976f8063 | |||
| 3e7c9fc81e | |||
| a1f4d7b16f | |||
| 811ef4a444 | |||
| 69ac621f5a | |||
| 610582df38 | |||
| cf16692b5a | |||
| 5d60440a6f | |||
| 0fe96e80c9 | |||
| a712726065 | |||
| 253b9dab27 | |||
| 1ffde1e9a6 | |||
| f6e0dfe9dc | |||
| 30dfd2772b | |||
| f93364ab96 | |||
| b903e0503f | |||
| b0ccb040a1 | |||
| db030ffa31 | |||
| cf90e9a6b8 | |||
| 7c451411cb | |||
| bf19d61d14 | |||
| 2cd5551913 | |||
| 3a3917c1fc | |||
| 7e798e18e8 | |||
| 9cb5026a0a | |||
| 39a9d68f43 | |||
| 8c54f2edc9 | |||
| d26b12137b | |||
| 081d6f9158 | |||
| b52439f8f1 | |||
| d63f83f7c7 | |||
| 85158abb5f | |||
| c917fc37ae | |||
| f68cdf43e1 | |||
| f0742c9d7c | |||
| 32e21b0314 | |||
| 22c035c9b9 | |||
| 4257d85aa7 | |||
| 9c50c67319 | |||
| d0c4b2ab72 | |||
| 53a0c55b14 | |||
| d76b8d91b1 | |||
| 44943e367f | |||
| 89c3c71251 | |||
| 7e7725f0f5 | |||
| 7b881a2110 | |||
| ccb078c8f2 | |||
| 974f827e8b | |||
| 048a8683dd | |||
| bdd7d7280d | |||
| 671026cfc9 | |||
| 56315768e9 | |||
| 309675dce7 | |||
| b42959f663 | |||
| 30979f92cc | |||
| 623e8e3979 | |||
| 42b2b16f0e | |||
| f14989f7fd | |||
| acf7fa7907 | |||
| aa9751afff | |||
| 3be714d786 | |||
| bcd1395e08 | |||
| 96199caa11 | |||
| 73de12037e | |||
| 1a8c89b99a | |||
| fdf53b8550 | |||
| 5487ec1d5f | |||
| 7b28e64c9e | |||
| 88a0189f23 | |||
| 95d8fe239e | |||
| 8ad814a3b6 | |||
| b5fb6bc2d5 | |||
| 9901b2ee3d | |||
| 346d13174a | |||
| 79ad33dd6e | |||
| 805d743f69 | |||
| a85f3bfc16 | |||
| 84cac6ac90 | |||
| e758bf2eca | |||
| 1f0a4490a6 | |||
| 85a4a4fa81 | |||
| aaf49667ec | |||
| a7029e4733 | |||
| 18b1857539 | |||
| 4f5c24d2e3 | |||
| f82d8a5df1 | |||
| cb3ed7ed8d | |||
| 1cade7f8c7 | |||
| 7503a83219 | |||
| 869e0dcbd2 | |||
| a814b51682 | |||
| c204741fb9 | |||
| 5f64b2cf37 | |||
| 9efa67224e | |||
| b00776901c | |||
| 37211b9a2c | |||
| 40c35e5851 | |||
| 68073fdb8b | |||
| 5eb9138775 | |||
| cb6b8434f0 | |||
| ff7bdb0f5b | |||
| 38953212a3 | |||
| 8e1e7a8676 | |||
| a296437547 | |||
| 012c3289cd | |||
| 48dd3fe0c7 | |||
| 367d82d103 | |||
| b7aadaa3d2 | |||
| 05d59bba73 | |||
| d5baa586cf | |||
| a1d7f2d8b3 | |||
| 3496a064c9 | |||
| 7c96f95491 | |||
| 7fc474d62b | |||
| 6a7229e983 | |||
| f4d507eaa0 | |||
| c962a9331a | |||
| b175177770 | |||
| 08ff284121 | |||
| 221183d791 | |||
| be84db097a | |||
| eaaccdad75 | |||
| 4fcadc7e94 | |||
| d77f95f29b | |||
| 2751a4a02d | |||
| 437a9cf2b3 | |||
| aef1fb13b1 | |||
| db5697c455 | |||
| 10d368696d | |||
| ef2e86b271 | |||
| 1c0188351c | |||
| 6d3377cc6e | |||
| fd6caf5cee | |||
| 20e265491f | |||
| 10c8645b5f | |||
| 3c353fc7f9 | |||
| bc04f578e3 | |||
| 03a8ee437d | |||
| ee0297bb69 | |||
| 9765e9cf3a | |||
| 6d9aba0952 | |||
| 1b137bb785 | |||
| d57561b0e3 | |||
| d2dc4efed8 | |||
| 4f02a13a46 | |||
| 52c33055af | |||
| bef6b8cd4c | |||
| 8d1cdf020b | |||
| 29b64965ed | |||
| 1e5a7a13dd | |||
| e6cc90f6dd | |||
| c29af1df48 | |||
| 8451a020dd | |||
| b413d717e2 | |||
| dafaca414c | |||
| b1fda57e50 | |||
| 4cd8522921 | |||
| 4574aa2173 | |||
| 226f8f60ca | |||
| a3d4ccc062 | |||
| 7ca323d8d3 | |||
| d35b47b960 | |||
| 00ad45f436 | |||
| d75179b742 | |||
| 6be183f11b | |||
| a979f7ab12 | |||
| e639869bb1 | |||
| 09552d282f | |||
| afe09c0850 | |||
| 0695839717 | |||
| 181f7c1819 | |||
| 12dba80553 | |||
| f1d26d0990 | |||
| 83d5eda63c | |||
| 2f80d5466d | |||
| e90766ad06 | |||
| 3c21ccab78 | |||
| 379c629e9c | |||
| 3f0ea176e3 | |||
| 49417cbce4 | |||
| 6153c70ef6 | |||
| dffe09af58 | |||
| 07e9a3a4ea | |||
| e3973de880 | |||
| 8e114f1e8f | |||
| b21289a32f | |||
| 52cf5b5ec3 | |||
| 3fbf90e56d | |||
| 73fbe7d78c | |||
| 3890353ff5 | |||
| f285af8a4e | |||
| 3b77c301c3 | |||
| 61718f9450 | |||
| 115ba8dcb8 | |||
| 9b086c7fdd | |||
| b788a6c642 | |||
| a94f7e6ec0 | |||
| 260ec800c2 | |||
| 9e223eb891 | |||
| bea7387459 | |||
| 99ff86aefb | |||
| 918bb761b2 | |||
| 031f70f529 | |||
| 25f9fecc16 | |||
| 76a10fc776 | |||
| 1d0b5f3251 | |||
| b01f8799ae | |||
| 76fb595a55 | |||
| fbb46c9ffe | |||
| 628f5b283f | |||
| 73c34fda9c | |||
| b442fecca7 | |||
| 9e1d3220c2 | |||
| de7294335f | |||
| 416dcdf90f | |||
| 2cd5b252d5 | |||
| 64cbeb4c9d | |||
| 5d1340e864 | |||
| d2deaf0375 | |||
| 95ff94c532 | |||
| 9f82ae1db7 | |||
| 11b5123bbb | |||
| d0dc5406cc | |||
| 3be1cd8b0d | |||
| 7134373933 | |||
| e2a821c257 | |||
| ed54301914 | |||
| 6849274b98 | |||
| 8fa838e8fb | |||
| 2f9753cc12 | |||
| 66263a44a5 | |||
| 425df19c5c | |||
| f9babe1882 | |||
| cd2f512284 | |||
| 624975b4c9 | |||
| 85cdc79fd2 | |||
| 374bbc0973 | |||
| 5a3b97c669 | |||
| 570b71820f | |||
| 442160bb7a | |||
| f87764f9d5 | |||
| 9d4e0f1e3d | |||
| 800b8b5f7e | |||
| c10c1f8fac | |||
| dbd9240142 | |||
| c3ca651e4a | |||
| f2e319a01f | |||
| d6589960f2 | |||
| 2847a28e74 | |||
| e29668a01b | |||
| 757108446d | |||
| 19715ef45f | |||
| a1c7352da1 | |||
| ae3c17073b | |||
| 59dd6e0941 | |||
| a321d4d1b8 | |||
| 22ac571c7d | |||
| 40d3f2ffb9 | |||
| 0c0802e964 | |||
| 2a6d5846d1 | |||
| a43847bc8b | |||
| df6bb36876 | |||
| d185f93c35 | |||
| df2ce2c133 | |||
| 5e90e74969 | |||
| 924ee5c413 | |||
| bceed10bd8 | |||
| dec7ef8f3f | |||
| f019900619 | |||
| ad92006f54 | |||
| 439935430a | |||
| 1de9dbf18c | |||
| 394cab5ab4 | |||
| 6efd14eff3 | |||
| e468492064 | |||
| 140d3c0268 | |||
| 349cb91e3a | |||
| abf70cd302 | |||
| 880c9cf679 | |||
| bf59510c68 | |||
| b67250c3d5 | |||
| 86833aa8bf | |||
| 4dcc4807ed | |||
| 90b562a0a1 | |||
| fc2b3d7fc7 | |||
| 4d50dcea61 | |||
| 1f9594eef4 | |||
| 5a88ff774c | |||
| b269760b21 | |||
| 3efd038906 | |||
| 2d72a66879 | |||
| 7dc50fda26 | |||
| ff602da0fa | |||
| 4b156ba27e | |||
| d9cf9cee88 | |||
| afa4c7b697 | |||
| a2a8c8fbd7 | |||
| 52c4d80cfc | |||
| 5d4d209030 | |||
| d9f453d860 | |||
| 8c51e8bad8 | |||
| d4b21243ca | |||
| 927add6f44 | |||
| 48317d7e61 | |||
| 93df2edec2 | |||
| 028ddfe290 | |||
| 39a4f141d7 | |||
| c350904219 | |||
| 3d09157091 | |||
| 040486c32b | |||
| 3b6d557dd4 | |||
| 74f4b60a21 | |||
| 5464107a9a | |||
| 84345a7e37 | |||
| cd3191012f | |||
| ef9cc2da3a | |||
| 12fd5c642d | |||
| a9b71f8533 | |||
| c73749ea54 | |||
| e001ed93c1 | |||
| 4e195543ea | |||
| 2c918a2015 | |||
| c867f609f1 | |||
| 182d671e31 | |||
| f15301a7a0 | |||
| 69879dc8f8 | |||
| 3b2ae6bc4a | |||
| b714cbbd72 | |||
| 09afb93ec3 | |||
| ab4cb08c7d | |||
| 2e877aa446 | |||
| d3eff734aa | |||
| b52f234c02 | |||
| f663a13391 | |||
| 5baaed19d0 | |||
| 183e7e5910 | |||
| 173392f26e | |||
| be26527b27 | |||
| 414374498f | |||
| 1443618857 | |||
| a7075422dc | |||
| 9213304161 | |||
| 46fdd605ae | |||
| 99598ec060 | |||
| 0ae1453fb1 | |||
| f63e8d7aed | |||
| 5342d819d9 | |||
| ca20fb799d | |||
| c760a7c50d | |||
| 2a3019f1b4 | |||
| 896d7aa788 | |||
| b7eb81dc76 | |||
| a72fae333a | |||
| 4eef90fe25 | |||
| 428df7ae4a | |||
| 1fd4995edc | |||
| 667a731164 | |||
| 0c5acb7f32 | |||
| 470ccd1ffc | |||
| e12984af4c | |||
| 7a6a6409c4 | |||
| 7c0f8db31b | |||
| f87ba4f0d5 | |||
| fed5a14e1b | |||
| b681ca5e17 | |||
| cb853168c6 | |||
| c3640f2a3d | |||
| 70b325a189 | |||
| 80b23f8fa7 | |||
| 6d08d9b7b0 | |||
| 6b0292db64 | |||
| 1d80fc66af | |||
| 010e4edc83 | |||
| b7f2152535 | |||
| 5f0dc4a58e | |||
| 5667256d2c | |||
| c092d871c1 | |||
| e1e73f5e5f | |||
| 23a8777cde | |||
| 0e2e47d4ee | |||
| dc8a37b489 | |||
| 47ec2572f5 | |||
| bff9dfedcc | |||
| 1b161c8dbe | |||
| 5a76e380de | |||
| 6a4966136d | |||
| 0a0e34d806 | |||
| 214db84f9d | |||
| 61fd3fc505 | |||
| 70789e3676 | |||
| a7de549e4f | |||
| efab275c99 | |||
| f8600725b2 | |||
| a5c1b0b2f2 | |||
| bd5833ec5f | |||
| 070fc368b2 | |||
| 50ed207211 | |||
| 4ea0fa0a19 | |||
| b5dd742257 | |||
| 0f4185b6a5 | |||
| ccea64f0fa | |||
| b892f98834 | |||
| 2f86813a21 | |||
| 2cd92353ec | |||
| 42ad3af48b | |||
| afb0aa8099 | |||
| e13e86b25f | |||
| 6b9930df6a | |||
| ae92c8219d | |||
| 512e59871e | |||
| 7545c0c1da | |||
| 3f8df66385 | |||
| 44257e361a | |||
| e94b6fa3a8 | |||
| 3621c20f80 | |||
| ef4d28299a | |||
| d4b718d615 | |||
| 280826f3e8 | |||
| 0a0d845173 | |||
| a999fca349 | |||
| c853263894 | |||
| 16f63b7fd9 | |||
| d41035cb2d | |||
| 1cb0cd296c | |||
| 8f100a7e9f | |||
| ed95ccc18e | |||
| e88264d0f7 | |||
| d9d8bae376 | |||
| 6f76377a9e | |||
| 3fdf13a8b1 | |||
| 23ea9e71fd | |||
| 19037ee1ba | |||
| 8abf6fc2b5 | |||
| 5a6e63e8d4 | |||
| 23341d8c76 | |||
| 5cbfa7bd91 | |||
| b3a93e369a | |||
| 5d7902a9a7 | |||
| c41c727e06 | |||
| 10aad7e048 | |||
| cc396c8b96 | |||
| 1a7fbf5927 | |||
| b28d719ee6 | |||
| d5c8430cd2 | |||
| e3acdbe85b | |||
| ef2c46b6ab | |||
| b9398375f1 | |||
| 274819f75f | |||
| fb3b99a49a | |||
| ffd4e9507b | |||
| 7212015127 | |||
| 31a1ee9145 | |||
| 53fbb18f1c | |||
| 43cfabe9e7 | |||
| caf972cd0f | |||
| 5bef3593dd | |||
| 3f233ad4a4 | |||
| 9252dc222a | |||
| fafe056db0 | |||
| 9f30a9b0fc | |||
| 86f6c4a39d | |||
| 32470e9bd2 | |||
| 97c18980d8 | |||
| defc9d3bc2 | |||
| 77e672aec1 | |||
| 519b06fe30 | |||
| 7e1b20e600 | |||
| 023c7f3fe7 | |||
| 89b8fe93b7 | |||
| f6cd597841 | |||
| fa48af02a1 | |||
| 8509aef99a | |||
| 46e939715a | |||
| 8a32f02781 | |||
| 573192c33f | |||
| 56f5789976 | |||
| f21265c7ae | |||
| eace046342 | |||
| 0a6a41e4c2 | |||
| b449973403 | |||
| 911e81e4af | |||
| 458e7dde94 | |||
| 0c7826b250 | |||
| ef0ad41c8e | |||
| fff1da2a12 | |||
| f91f25e5c0 | |||
| 3f35ca1e77 | |||
| 8c619e92d9 | |||
| d4fd58e038 | |||
| 2961370b83 | |||
| c71e00b3dc | |||
| 641c7dfa04 | |||
| 95845c8f2e | |||
| c656bb632e | |||
| bf82a70744 | |||
| 520955a8db | |||
| 2b25815eee | |||
| 7cfcab4011 | |||
| 787e10bbe1 | |||
| 8328f09d6b | |||
| 04823c23a0 | |||
| 5af67facad | |||
| be9e4c9623 | |||
| e03988dd81 | |||
| 79990b6a6c | |||
| 7f78aef05f | |||
| df3d427c0b | |||
| e558918432 | |||
| e6d1eb0ba0 | |||
| f32a46c546 | |||
| a4de37efb9 |
@@ -76,6 +76,7 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
|
||||
|
||||
@@ -129,3 +130,4 @@ src/*.boltdata/
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
|
||||
src/umbraco.sln.ide/*
|
||||
build/UmbracoCms.*/
|
||||
src/.vs/
|
||||
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
# The MIT License (MIT) #
|
||||
|
||||
Copyright (c) 2013 Umbraco
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
# The MIT License (MIT) #
|
||||
|
||||
Copyright (c) 2013 Umbraco
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
+8
-6
@@ -25,9 +25,9 @@ ECHO Installing the Microsoft.Bcl.Build package before anything else, otherwise
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
..\src\.nuget\NuGet.exe sources Remove -Name MyGetUmbracoCore >NUL
|
||||
..\src\.nuget\NuGet.exe sources Add -Name MyGetUmbracoCore -Source https://www.myget.org/F/umbracocore/api/v2/ >NUL
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder%
|
||||
..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder%
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder%
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
|
||||
..\src\.nuget\NuGet.exe install ..\src\umbraco.businesslogic\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Core\packages.config -OutputDirectory %nuGetFolder% -Verbosity quiet
|
||||
|
||||
ECHO Removing the belle build folder and bower_components folder to make sure everything is clean as a whistle
|
||||
RD ..\src\Umbraco.Web.UI.Client\build /Q /S
|
||||
@@ -43,7 +43,7 @@ DEL /F /Q webpihash.txt
|
||||
ECHO Making sure Git is in the path so that the build can succeed
|
||||
CALL InstallGit.cmd
|
||||
ECHO Performing MSBuild and producing Umbraco binaries zip files
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment% /verbosity:minimal
|
||||
|
||||
ECHO Setting node_modules folder to hidden to prevent VS13 from crashing on it while loading the websites project
|
||||
attrib +h ..\src\Umbraco.Web.UI.Client\node_modules
|
||||
@@ -53,11 +53,13 @@ REN .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
|
||||
REN .\_BuildOutput\WebApp\Xslt\Web.config Web.config.transform
|
||||
|
||||
ECHO Packing the NuGet release files
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version%
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.Core.nuspec -Version %version% -Symbols -Verbosity quiet
|
||||
..\src\.nuget\NuGet.exe Pack NuSpecs\UmbracoCms.nuspec -Version %version% -Verbosity quiet
|
||||
|
||||
IF ERRORLEVEL 1 GOTO :showerror
|
||||
|
||||
ECHO No errors were detected but you still may see some in the output, then it's time to investigate.
|
||||
ECHO You might see some warnings but that is completely normal.
|
||||
GOTO :EOF
|
||||
|
||||
:showerror
|
||||
|
||||
+45
-13
@@ -68,6 +68,12 @@
|
||||
<PropertyGroup Condition="'$(BUILD_RELEASE)'!='' AND '$(BUILD_COMMENT)'!=''">
|
||||
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)-$(BUILD_COMMENT)</DECIMAL_BUILD_NUMBER>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(BUILD_RELEASE)'!='' AND '$(BUILD_NIGHTLY)'!=''">
|
||||
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)-$(BUILD_NIGHTLY)</DECIMAL_BUILD_NUMBER>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(BUILD_RELEASE)'!='' AND '$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''">
|
||||
<DECIMAL_BUILD_NUMBER>.$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)</DECIMAL_BUILD_NUMBER>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<BuildConfiguration>Release</BuildConfiguration>
|
||||
@@ -91,15 +97,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<SystemFolders Include="$(WebAppFolder)App_Plugins" />
|
||||
<SystemFolders Include="$(WebAppFolder)App_Code" />
|
||||
<SystemFolders Include="$(WebAppFolder)App_Data" />
|
||||
<SystemFolders Include="$(WebAppFolder)Media" />
|
||||
<SystemFolders Include="$(WebAppFolder)Masterpages" />
|
||||
<SystemFolders Include="$(WebAppFolder)Scripts" />
|
||||
<SystemFolders Include="$(WebAppFolder)Css" />
|
||||
<SystemFolders Include="$(WebAppFolder)Xslt" />
|
||||
<SystemFolders Include="$(WebAppFolder)UserControls" />
|
||||
<SystemFolders Include="$(WebAppFolder)Views" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -145,14 +144,14 @@
|
||||
DestinationFiles="@(WebPiFiles->'$(WebPiFolder)%(RecursiveDir)%(Filename)%(Extension)')" />
|
||||
|
||||
<!-- Zip the files -->
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameWebPi)%22 %22$(WebPiFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameWebPi)%22 %22$(WebPiFolderAbsolutePath)*%22 -x!dotLess.Core.dll -x![Content_Types].xml >NUL" />
|
||||
</Target>
|
||||
|
||||
<Target Name="ZipWebApp" DependsOnTargets="CreateSystemFolders" >
|
||||
<Message Text="Starting to zip to $(buildDate)-$(BuildZipFileName)" Importance="high" />
|
||||
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22 -x!dotLess.Core.dll" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileNameBin)%22 %22$(SolutionBinFolderAbsolutePath)*%22 -x!dotLess.Core.dll >NUL" />
|
||||
<Exec Command="..\tools\7zip\7za.exe a -r %22$(BuildZipFileName)%22 %22$(WebAppFolderAbsolutePath)*%22 -x!dotLess.Core.dll -x![Content_Types].xml >NUL" />
|
||||
|
||||
<Message Text="Finished zipping to build\$(BuildFolder)\$(buildDate)-$(BuildZipFileName)" Importance="high" />
|
||||
</Target>
|
||||
@@ -219,6 +218,7 @@
|
||||
<Target Name="CopyTransformedConfig" DependsOnTargets="CopyXmlDocumentation">
|
||||
<ItemGroup>
|
||||
<ConfigFiles Include="$(WebAppFolder)config\*.config;$(WebAppFolder)config\*.js" />
|
||||
<CustomLanguageFiles Include="$(WebAppFolder)config\lang\*.xml" />
|
||||
<WebConfigTransformFile Include="$(WebAppFolder)Web.config" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -227,6 +227,11 @@
|
||||
OverwriteReadOnlyFiles="true"
|
||||
SkipUnchangedFiles="false" />
|
||||
|
||||
<Copy SourceFiles="@(CustomLanguageFiles)"
|
||||
DestinationFiles="@(CustomLanguageFiles->'$(ConfigsFolder)Lang\%(RecursiveDir)%(Filename)%(Extension)')"
|
||||
OverwriteReadOnlyFiles="true"
|
||||
SkipUnchangedFiles="false" />
|
||||
|
||||
<Copy SourceFiles="@(WebConfigTransformFile)"
|
||||
DestinationFiles="$(ConfigsFolder)Web.config.transform"
|
||||
OverwriteReadOnlyFiles="true"
|
||||
@@ -259,20 +264,23 @@
|
||||
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
|
||||
<!-- For UseWPP_CopyWebApplication=True see http://stackoverflow.com/questions/1983575/copywebapplication-with-web-config-transformations -->
|
||||
<!-- Build the Umbraco.Web.UI project -->
|
||||
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath)" Targets="Clean;Rebuild;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False">
|
||||
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath);Verbosity=minimal" Targets="Clean;Rebuild;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False">
|
||||
</MSBuild>
|
||||
|
||||
<!-- DONE -->
|
||||
<Message Text="Finished compiling projects" Importance="high" />
|
||||
</Target>
|
||||
|
||||
|
||||
<Target Name="SetVersionNumber" Condition="'$(BUILD_RELEASE)'!=''">
|
||||
<PropertyGroup>
|
||||
<NewVersion>$(BUILD_RELEASE)</NewVersion>
|
||||
<NewVersion Condition="'$(BUILD_COMMENT)'!=''">$(BUILD_RELEASE)-$(BUILD_COMMENT)</NewVersion>
|
||||
<NewVersion Condition="'$(BUILD_NIGHTLY)'!=''">$(BUILD_RELEASE)-$(BUILD_NIGHTLY)</NewVersion>
|
||||
<NewVersion Condition="'$(BUILD_COMMENT)'!='' And '$(BUILD_NIGHTLY)'!=''">$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)</NewVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Match & replace 3 and 4 digit version numbers and -beta (if it's there) -->
|
||||
<!-- Match & replace 3 and 4 digit version numbers and -beta and +nightly (if they're there) -->
|
||||
<FileUpdate
|
||||
Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
|
||||
Regex="(\d+)\.(\d+)\.(\d+)(.(\d+))?"
|
||||
@@ -282,6 +290,16 @@
|
||||
Regex="CurrentComment { get { return "(.+)?""
|
||||
ReplacementText="CurrentComment { get { return "$(BUILD_COMMENT)""/>
|
||||
|
||||
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
|
||||
Condition="'$(BUILD_NIGHTLY)'!=''"
|
||||
Regex="CurrentComment { get { return "(.+)?""
|
||||
ReplacementText="CurrentComment { get { return "$(BUILD_NIGHTLY)""/>
|
||||
|
||||
<FileUpdate Files="..\src\Umbraco.Core\Configuration\UmbracoVersion.cs"
|
||||
Condition="'$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''"
|
||||
Regex="CurrentComment { get { return "(.+)?""
|
||||
ReplacementText="CurrentComment { get { return "$(BUILD_COMMENT)-$(BUILD_NIGHTLY)""/>
|
||||
|
||||
<!--This updates the AssemblyFileVersion for the solution to the umbraco version-->
|
||||
<FileUpdate
|
||||
Files="..\src\SolutionInfo.cs"
|
||||
@@ -299,10 +317,24 @@
|
||||
Files="..\src\SolutionInfo.cs"
|
||||
Regex="AssemblyInformationalVersion\("(.+)?"\)"
|
||||
ReplacementText="AssemblyInformationalVersion("$(BUILD_RELEASE)")"/>
|
||||
<FileUpdate
|
||||
Condition="'$(BUILD_NIGHTLY)'!=''"
|
||||
Files="..\src\SolutionInfo.cs"
|
||||
Regex="AssemblyInformationalVersion\("(.+)?"\)"
|
||||
ReplacementText="AssemblyInformationalVersion("$(BUILD_RELEASE)-$(BUILD_NIGHTLY)")"/>
|
||||
<FileUpdate
|
||||
Condition="'$(BUILD_COMMENT)'!='' AND '$(BUILD_NIGHTLY)'!=''"
|
||||
Files="..\src\SolutionInfo.cs"
|
||||
Regex="AssemblyInformationalVersion\("(.+)?"\)"
|
||||
ReplacementText="AssemblyInformationalVersion("$(BUILD_RELEASE)-$(BUILD_COMMENT)-$(BUILD_NIGHTLY)")"/>
|
||||
<FileUpdate
|
||||
Condition="'$(BUILD_COMMENT)'=='' AND '$(BUILD_NIGHTLY)'==''"
|
||||
Files="..\src\SolutionInfo.cs"
|
||||
Regex="AssemblyInformationalVersion\("(.+)?"\)"
|
||||
ReplacementText="AssemblyInformationalVersion("$(BUILD_RELEASE)")"/>
|
||||
|
||||
<!--This updates the copyright year-->
|
||||
<FileUpdate
|
||||
Condition="'$(BUILD_COMMENT)'==''"
|
||||
Files="..\src\SolutionInfo.cs"
|
||||
Regex="AssemblyCopyright\("Copyright © Umbraco (\d{4})"\)"
|
||||
ReplacementText="AssemblyCopyright("Copyright © Umbraco $([System.DateTime]::Now.ToString(`yyyy`))")"/>
|
||||
|
||||
@@ -6,7 +6,7 @@ SET nuGetFolder=%CD%\..\src\packages\
|
||||
ECHO Configured packages folder: %nuGetFolder%
|
||||
ECHO Current folder: %CD%
|
||||
|
||||
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder%
|
||||
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
|
||||
|
||||
for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
|
||||
for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
|
||||
@@ -24,9 +24,9 @@ ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
CD %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
|
||||
ECHO Do npm install and the grunt build of Belle
|
||||
call npm install
|
||||
call npm install -g grunt-cli
|
||||
call npm install -g bower
|
||||
call npm install --quiet
|
||||
call npm install -g grunt-cli --quiet
|
||||
call npm install -g bower --quiet
|
||||
call grunt build --buildversion=%release%
|
||||
|
||||
ECHO Reset path to what it was before
|
||||
|
||||
@@ -15,26 +15,29 @@
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[4.0.30506.0,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[4.0.30506,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi.WebHost" version="[4.0.30506, 6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi.Core" version="[4.0.30506, 6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi.Client" version="[4.0.30506, 6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc.FixedDisplayModes" version="1.0.1" />
|
||||
<dependency id="Microsoft.Net.Http" version="[2.0.20710.0, 3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.Net.Http" version="[2.2.29, 3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.6, 2.0.0)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.6, 7.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.7, 7.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.8.3.1, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc" version="[1.8.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.0.0, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.5, 7.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.63, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[1.9.5, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[3.3.1, 5.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.8.4, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.0.0, 3.1.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[6.0.8, 7.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.68, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.3.0, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.4.0, 5.0.0)" />
|
||||
<dependency id="semver" version="[1.1.2, 2.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebHelpers" version="[3.2.3, 4.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebPages.Data" version="[3.2.3, 4.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="..\_BuildOutput\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="..\_BuildOutput\WebApp\App_Plugins\**" target="UmbracoFiles\App_Plugins" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\amd64\**" target="UmbracoFiles\bin\amd64" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\x86\**" target="UmbracoFiles\bin\x86" />
|
||||
<file src="..\_BuildOutput\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
@@ -41,6 +40,7 @@
|
||||
<file src="tools\Dashboard.config.install.xdt" target="Content\config\Dashboard.config.install.xdt" />
|
||||
<file src="tools\trees.config.install.xdt" target="Content\config\trees.config.install.xdt" />
|
||||
<file src="tools\umbracoSettings.config.install.xdt" target="Content\config\umbracoSettings.config.install.xdt" />
|
||||
<file src="tools\Views.Web.config.install.xdt" target="Views\Web.config.install.xdt" />
|
||||
<file src="build\**" target="build" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>UmbracoExamine.PDF</id>
|
||||
<version>0.7.0</version>
|
||||
<authors>Umbraco HQ</authors>
|
||||
<owners>Umbraco HQ</owners>
|
||||
<licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
|
||||
<projectUrl>http://umbraco.com/</projectUrl>
|
||||
<iconUrl>http://umbraco.com/media/357769/100px_transparent.png</iconUrl>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>UmbracoExmine.PDF</description>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[7.0.0, 8.0.0)" />
|
||||
<dependency id="iTextSharp" version="[5.5.3, 6.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="..\_BuildOutput\UmbracoExamine.PDF\UmbracoExamine.PDF.dll" target="lib\UmbracoExamine.PDF.dll" />
|
||||
<file src="..\_BuildOutput\UmbracoExamine.PDF\UmbracoExamine.PDF.XML" target="lib\UmbracoExamine.PDF.XML" />
|
||||
</files>
|
||||
</package>
|
||||
@@ -35,6 +35,11 @@
|
||||
views/dashboard/developer/examinemanagement.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Xml Data Integrity Report" xdt:Transform="InsertIfMissing">
|
||||
<control>
|
||||
views/dashboard/developer/xmldataintegrityreport.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)">
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<configSections>
|
||||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(name)"
|
||||
xdt:Transform="SetAttributes(type)">
|
||||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(name)"
|
||||
xdt:Transform="SetAttributes(type)" />
|
||||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(name)"
|
||||
xdt:Transform="SetAttributes(type)" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(factoryType)"
|
||||
xdt:Transform="SetAttributes(factoryType)" />
|
||||
</system.web.webPages.razor>
|
||||
|
||||
<system.web>
|
||||
<pages
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(pageParserFilterType,pageBaseType,userControlBaseType)"
|
||||
xdt:Transform="SetAttributes(pageParserFilterType,pageBaseType,userControlBaseType)">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc"
|
||||
xdt:Locator="Match(namespace)"
|
||||
xdt:Transform="SetAttributes(assembly)" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
</configuration>
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
<appSettings xdt:Transform="InsertIfMissing" />
|
||||
<appSettings>
|
||||
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" xdt:Locator="Match(key)" xdt:Transform="InsertIfMissing" />
|
||||
</appSettings>
|
||||
|
||||
|
||||
<umbracoConfiguration xdt:Transform="InsertIfMissing">
|
||||
<settings configSource="config\umbracoSettings.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<BaseRestExtensions configSource="config\BaseRestExtensions.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
@@ -48,6 +48,8 @@
|
||||
<system.web xdt:Transform="InsertIfMissing" />
|
||||
<system.web>
|
||||
<siteMap xdt:Transform="Remove" />
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime targetFramework="4.5" xdt:Transform="SetAttributes(targetFramework)" />
|
||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
|
||||
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
|
||||
@@ -143,6 +145,12 @@
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Newtonsoft.Json')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Mvc')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Web.Http')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security.OAuth')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security.Cookies')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -158,7 +166,31 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -58,6 +58,7 @@ if ($project) {
|
||||
if(Test-Path $umbracoBinFolder\ImageProcessor.Web.dll) { Remove-Item $umbracoBinFolder\ImageProcessor.Web.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Lucene.Net.dll) { Remove-Item $umbracoBinFolder\Lucene.Net.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.Web.Infrastructure.dll) { Remove-Item $umbracoBinFolder\Microsoft.Web.Infrastructure.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.Web.Helpers.dll) { Remove-Item $umbracoBinFolder\Microsoft.Web.Helpers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Microsoft.Web.Mvc.FixedDisplayModes.dll) { Remove-Item $umbracoBinFolder\Microsoft.Web.Mvc.FixedDisplayModes.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\MiniProfiler.dll) { Remove-Item $umbracoBinFolder\MiniProfiler.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\MySql.Data.dll) { Remove-Item $umbracoBinFolder\MySql.Data.dll -Force -Confirm:$false }
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0"?>
|
||||
<log4net xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<appender name="AsynchronousLog4NetAppender" xdt:Transform="Remove" xdt:Locator="Match(name)" />
|
||||
<appender name="AsynchronousLog4NetAppender" type="Umbraco.Core.Logging.ParallelForwardingAppender,Umbraco.Core" xdt:Transform="Insert" >
|
||||
<appender-ref ref="rollingFile" />
|
||||
</appender>
|
||||
|
||||
<appender name="rollingFile" type="log4net.Appender.RollingFileAppender" xdt:Transform="InsertIfMissing">
|
||||
<file value="App_Data\Logs\UmbracoTraceLog.txt" />
|
||||
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
|
||||
<appendToFile value="true" />
|
||||
<rollingStyle value="Date" />
|
||||
<maximumFileSize value="5MB" />
|
||||
<layout type="log4net.Layout.PatternLayout">
|
||||
<conversionPattern value=" %date [P%property{processId}/D%property{appDomainId}/T%thread] %-5level %logger - %message%newline" />
|
||||
</layout>
|
||||
<encoding value="utf-8" />
|
||||
</appender>
|
||||
</log4net>
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
<add initialize="false" sortOrder="0" alias="mediaRecycleBin" application="media" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.MediaRecycleBin, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="stylesheets" title="Stylesheets" type="umbraco.loadStylesheets, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="0" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, umbraco" iconClosed="" iconOpen="" initialize="false" sortOrder="0" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="templates" title="Templates" type="umbraco.loadTemplates, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="1" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add alias="dictionary" xdt:Locator="Match(alias)" xdt:Transform="RemoveAttributes(action)" />
|
||||
<add application="settings" alias="languages" title="Languages" type="umbraco.loadLanguages, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="languages" title="Languages" type="Umbraco.Web.Trees.LanguageTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="5" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="mediaTypes" title="Media Types" type="umbraco.loadMediaTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="nodeTypes" title="Document Types" type="umbraco.loadNodeTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="7" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
<add initialize="true" sortOrder="0" alias="datatype" application="developer" title="Data Types" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco" xdt:Locator="Match(alias)" xdt:Transform="SetAttributes()" />
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.2.6
|
||||
7.3.0
|
||||
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
|
||||
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -77,8 +77,9 @@
|
||||
<Compile Include="SqlCEUtility.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
<None Include="app.config" />
|
||||
<None Include="app.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">CSharp50</s:String></wpf:ResourceDictionary>
|
||||
@@ -14,6 +14,22 @@
|
||||
<assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
</configuration>
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.2.6")]
|
||||
[assembly: AssemblyInformationalVersion("7.2.6")]
|
||||
[assembly: AssemblyFileVersion("7.3.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.3.0")]
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using umbraco.interfaces;
|
||||
|
||||
@@ -12,13 +13,14 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal sealed class ActionsResolver : LazyManyObjectsResolverBase<ActionsResolver, IAction>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="packageActions"></param>
|
||||
internal ActionsResolver(Func<IEnumerable<Type>> packageActions)
|
||||
: base(packageActions)
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="packageActions"></param>
|
||||
internal ActionsResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> packageActions)
|
||||
: base(serviceProvider, logger, packageActions)
|
||||
{
|
||||
|
||||
}
|
||||
@@ -55,7 +57,7 @@ namespace Umbraco.Core
|
||||
var instance = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static);
|
||||
//if the singletone initializer is not found, try simply creating an instance of the IAction if it supports public constructors
|
||||
if (instance == null)
|
||||
typeInstance = PluginManager.Current.CreateInstance<IAction>(type);
|
||||
typeInstance = ServiceProvider.GetService(type) as IAction;
|
||||
else
|
||||
typeInstance = instance.GetValue(null, null) as IAction;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Helper methods for Activation
|
||||
/// </summary>
|
||||
internal static class ActivatorHelper
|
||||
@@ -14,7 +12,9 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
public static T CreateInstance<T>() where T : class, new()
|
||||
{
|
||||
return Activator.CreateInstance(typeof(T)) as T;
|
||||
return new ActivatorServiceProvider().GetService(typeof (T)) as T;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
internal class ActivatorServiceProvider : IServiceProvider
|
||||
{
|
||||
public object GetService(Type serviceType)
|
||||
{
|
||||
return Activator.CreateInstance(serviceType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using Umbraco.Core.Profiling;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -21,30 +20,65 @@ namespace Umbraco.Core
|
||||
/// </remarks>
|
||||
public class ApplicationContext : IDisposable
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="serviceContext"></param>
|
||||
/// <param name="cache"></param>
|
||||
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache)
|
||||
{
|
||||
/// <param name="logger"></param>
|
||||
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger)
|
||||
{
|
||||
if (dbContext == null) throw new ArgumentNullException("dbContext");
|
||||
if (serviceContext == null) throw new ArgumentNullException("serviceContext");
|
||||
if (cache == null) throw new ArgumentNullException("cache");
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
_databaseContext = dbContext;
|
||||
_services = serviceContext;
|
||||
ApplicationCache = cache;
|
||||
ProfilingLogger = logger;
|
||||
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="serviceContext"></param>
|
||||
/// <param name="cache"></param>
|
||||
[Obsolete("Use the other constructor specifying a ProfilingLogger instead")]
|
||||
public ApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache)
|
||||
: this(dbContext, serviceContext, cache,
|
||||
new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a basic app context
|
||||
/// </summary>
|
||||
/// <param name="cache"></param>
|
||||
[Obsolete("Use the other constructor specifying a ProfilingLogger instead")]
|
||||
public ApplicationContext(CacheHelper cache)
|
||||
{
|
||||
if (cache == null) throw new ArgumentNullException("cache");
|
||||
ApplicationCache = cache;
|
||||
ProfilingLogger = new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler);
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a basic app context
|
||||
/// </summary>
|
||||
/// <param name="cache"></param>
|
||||
/// <param name="logger"></param>
|
||||
public ApplicationContext(CacheHelper cache, ProfilingLogger logger)
|
||||
{
|
||||
if (cache == null) throw new ArgumentNullException("cache");
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
ApplicationCache = cache;
|
||||
ProfilingLogger = logger;
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -60,13 +94,13 @@ namespace Umbraco.Core
|
||||
/// </remarks>
|
||||
public static ApplicationContext EnsureContext(ApplicationContext appContext, bool replaceContext)
|
||||
{
|
||||
if (ApplicationContext.Current != null)
|
||||
if (Current != null)
|
||||
{
|
||||
if (!replaceContext)
|
||||
return ApplicationContext.Current;
|
||||
return Current;
|
||||
}
|
||||
ApplicationContext.Current = appContext;
|
||||
return ApplicationContext.Current;
|
||||
Current = appContext;
|
||||
return Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -83,16 +117,44 @@ namespace Umbraco.Core
|
||||
/// <remarks>
|
||||
/// This is NOT thread safe
|
||||
/// </remarks>
|
||||
[Obsolete("Use the other method specifying an ProfilingLogger instead")]
|
||||
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, bool replaceContext)
|
||||
{
|
||||
if (ApplicationContext.Current != null)
|
||||
if (Current != null)
|
||||
{
|
||||
if (!replaceContext)
|
||||
return ApplicationContext.Current;
|
||||
return Current;
|
||||
}
|
||||
var ctx = new ApplicationContext(dbContext, serviceContext, cache);
|
||||
ApplicationContext.Current = ctx;
|
||||
return ApplicationContext.Current;
|
||||
Current = ctx;
|
||||
return Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A method used to create and ensure that a global ApplicationContext singleton is created.
|
||||
/// </summary>
|
||||
/// <param name="cache"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="replaceContext">
|
||||
/// If set to true will replace the current singleton instance - This should only be used for unit tests or on app
|
||||
/// startup if for some reason the boot manager is not the umbraco boot manager.
|
||||
/// </param>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="serviceContext"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// This is NOT thread safe
|
||||
/// </remarks>
|
||||
public static ApplicationContext EnsureContext(DatabaseContext dbContext, ServiceContext serviceContext, CacheHelper cache, ProfilingLogger logger, bool replaceContext)
|
||||
{
|
||||
if (Current != null)
|
||||
{
|
||||
if (!replaceContext)
|
||||
return Current;
|
||||
}
|
||||
var ctx = new ApplicationContext(dbContext, serviceContext, cache, logger);
|
||||
Current = ctx;
|
||||
return Current;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -108,7 +170,13 @@ namespace Umbraco.Core
|
||||
/// </remarks>
|
||||
public CacheHelper ApplicationCache { get; private set; }
|
||||
|
||||
// IsReady is set to true by the boot manager once it has successfully booted
|
||||
/// <summary>
|
||||
/// Exposes the global ProfilingLogger - this should generally not be accessed via the UmbracoContext and should normally just be exposed
|
||||
/// on most base classes or injected with IoC
|
||||
/// </summary>
|
||||
public ProfilingLogger ProfilingLogger { get; private set; }
|
||||
|
||||
// IsReady is set to true by the boot manager once it has successfully booted
|
||||
// note - the original umbraco module checks on content.Instance in umbraco.dll
|
||||
// now, the boot task that setup the content store ensures that it is ready
|
||||
bool _isReady = false;
|
||||
@@ -141,60 +209,111 @@ namespace Umbraco.Core
|
||||
// GlobalSettings.CurrentVersion returns the hard-coded "current version"
|
||||
// the system is configured if they match
|
||||
// if they don't, install runs, updates web.config (presumably) and updates GlobalSettings.ConfiguredStatus
|
||||
//
|
||||
// then there is Application["umbracoNeedConfiguration"] which makes no sense... getting rid of it... SD: I have actually remove that now!
|
||||
//
|
||||
|
||||
public bool IsConfigured
|
||||
{
|
||||
// todo - we should not do this - ok for now
|
||||
get { return _configured.Value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// If the db is configured, there is a database context and there is an umbraco schema, but we are not 'configured' , then it means we are upgrading
|
||||
/// </summary>
|
||||
public bool IsUpgrading
|
||||
{
|
||||
get
|
||||
{
|
||||
return Configured;
|
||||
if (IsConfigured == false
|
||||
&& DatabaseContext != null
|
||||
&& DatabaseContext.IsDatabaseConfigured)
|
||||
{
|
||||
var schemaresult = DatabaseContext.ValidateDatabaseSchema();
|
||||
if (schemaresult.ValidTables.Count > 0) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The application url.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The application url is the url that should be used by services to talk to the application,
|
||||
/// eg keep alive or scheduled publishing services. It must exist on a global context because
|
||||
/// some of these services may not run within a web context.
|
||||
/// The format of the application url is:
|
||||
/// - has a scheme (http or https)
|
||||
/// - has the SystemDirectories.Umbraco path
|
||||
/// - does not end with a slash
|
||||
/// It is initialized on the first request made to the server, by UmbracoModule.EnsureApplicationUrl:
|
||||
/// - if umbracoSettings:settings/web.routing/@umbracoApplicationUrl is set, use the value (new setting)
|
||||
/// - if umbracoSettings:settings/scheduledTasks/@baseUrl is set, use the value (backward compatibility)
|
||||
/// - otherwise, use the url of the (first) request.
|
||||
/// Not locking, does not matter if several threads write to this.
|
||||
/// See also issues:
|
||||
/// - http://issues.umbraco.org/issue/U4-2059
|
||||
/// - http://issues.umbraco.org/issue/U4-6788
|
||||
/// - http://issues.umbraco.org/issue/U4-5728
|
||||
/// - http://issues.umbraco.org/issue/U4-5391
|
||||
/// </remarks>
|
||||
internal string UmbracoApplicationUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
ApplicationUrlHelper.EnsureApplicationUrl(this);
|
||||
return _umbracoApplicationUrl;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The original/first url that the web application executes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// we need to set the initial url in our ApplicationContext, this is so our keep alive service works and this must
|
||||
/// exist on a global context because the keep alive service doesn't run in a web context.
|
||||
/// we are NOT going to put a lock on this because locking will slow down the application and we don't really care
|
||||
/// if two threads write to this at the exact same time during first page hit.
|
||||
/// see: http://issues.umbraco.org/issue/U4-2059
|
||||
/// </remarks>
|
||||
internal string OriginalRequestUrl { get; set; }
|
||||
// ReSharper disable once InconsistentNaming
|
||||
internal string _umbracoApplicationUrl;
|
||||
|
||||
private bool _versionsDifferenceReported;
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the version configured matches the assembly version
|
||||
/// </summary>
|
||||
private bool Configured
|
||||
private Lazy<bool> _configured;
|
||||
internal MainDom MainDom { get; private set; }
|
||||
|
||||
private void Init()
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
var configStatus = ConfigurationStatus;
|
||||
var currentVersion = UmbracoVersion.Current.ToString(3);
|
||||
var ok = configStatus == currentVersion;
|
||||
MainDom = new MainDom(ProfilingLogger.Logger);
|
||||
MainDom.Acquire();
|
||||
|
||||
//Create the lazy value to resolve whether or not the application is 'configured'
|
||||
_configured = new Lazy<bool>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
var configStatus = ConfigurationStatus;
|
||||
var currentVersion = UmbracoVersion.GetSemanticVersion();
|
||||
var ok = configStatus == currentVersion;
|
||||
|
||||
if (ok == false && _versionsDifferenceReported == false)
|
||||
{
|
||||
// remember it's been reported so we don't flood the log
|
||||
// no thread-safety so there may be a few log entries, doesn't matter
|
||||
_versionsDifferenceReported = true;
|
||||
LogHelper.Info<ApplicationContext>("CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + "'");
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (ok)
|
||||
{
|
||||
//The versions are the same in config, but are they the same in the database. We can only check this
|
||||
// if we have a db context available, if we don't then we are not installed anyways
|
||||
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.CanConnect)
|
||||
{
|
||||
var found = Services.MigrationEntryService.FindEntry(GlobalSettings.UmbracoMigrationName, UmbracoVersion.GetSemanticVersion());
|
||||
if (found == null)
|
||||
{
|
||||
//we haven't executed this migration in this environment, so even though the config versions match,
|
||||
// this db has not been updated.
|
||||
ProfilingLogger.Logger.Debug<ApplicationContext>(string.Format("The migration for version: '{0} has not been executed, there is no record in the database", currentVersion.ToSemanticString()));
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ProfilingLogger.Logger.Debug<ApplicationContext>(string.Format("CurrentVersion different from configStatus: '{0}','{1}'", currentVersion.ToSemanticString(), configStatus));
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private string ConfigurationStatus
|
||||
@@ -212,12 +331,6 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
private void AssertIsReady()
|
||||
{
|
||||
if (!this.IsReady)
|
||||
throw new Exception("ApplicationContext is not ready yet.");
|
||||
}
|
||||
|
||||
private void AssertIsNotReady()
|
||||
{
|
||||
if (this.IsReady)
|
||||
@@ -258,6 +371,11 @@ namespace Umbraco.Core
|
||||
internal set { _services = value; }
|
||||
}
|
||||
|
||||
internal ServerRole GetCurrentServerRole()
|
||||
{
|
||||
var registrar = ServerRegistrarResolver.Current.Registrar as IServerRegistrar2;
|
||||
return registrar == null ? ServerRole.Unknown : registrar.GetCurrentServerRole();
|
||||
}
|
||||
|
||||
private volatile bool _disposed;
|
||||
private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
|
||||
@@ -293,7 +411,7 @@ namespace Umbraco.Core
|
||||
this.ApplicationCache = null;
|
||||
if (_databaseContext != null) //need to check the internal field here
|
||||
{
|
||||
if (DatabaseContext.IsDatabaseConfigured)
|
||||
if (DatabaseContext.IsDatabaseConfigured && DatabaseContext.Database != null)
|
||||
{
|
||||
DatabaseContext.Database.Dispose();
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
private bool ShouldExecute(ApplicationContext applicationContext)
|
||||
{
|
||||
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.CanConnect)
|
||||
if (applicationContext.IsConfigured && applicationContext.DatabaseContext.IsDatabaseConfigured)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ namespace Umbraco.Core
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!applicationContext.DatabaseContext.CanConnect && ExecuteWhenDatabaseNotConfigured)
|
||||
if (!applicationContext.DatabaseContext.IsDatabaseConfigured && ExecuteWhenDatabaseNotConfigured)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,14 +63,14 @@ namespace Umbraco.Core
|
||||
// for anonymous semaphore, use the unique releaser, else create a new one
|
||||
return _semaphore != null
|
||||
? _releaser // (IDisposable)new SemaphoreSlimReleaser(_semaphore)
|
||||
: (IDisposable)new NamedSemaphoreReleaser(_semaphore2);
|
||||
: new NamedSemaphoreReleaser(_semaphore2);
|
||||
}
|
||||
|
||||
public Task<IDisposable> LockAsync()
|
||||
{
|
||||
var wait = _semaphore != null
|
||||
? _semaphore.WaitAsync()
|
||||
: WaitOneAsync(_semaphore2);
|
||||
? _semaphore.WaitAsync()
|
||||
: _semaphore2.WaitOneAsync();
|
||||
|
||||
return wait.IsCompleted
|
||||
? _releaserTask ?? Task.FromResult(CreateReleaser()) // anonymous vs named
|
||||
@@ -79,6 +79,19 @@ namespace Umbraco.Core
|
||||
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
public Task<IDisposable> LockAsync(int millisecondsTimeout)
|
||||
{
|
||||
var wait = _semaphore != null
|
||||
? _semaphore.WaitAsync(millisecondsTimeout)
|
||||
: _semaphore2.WaitOneAsync(millisecondsTimeout);
|
||||
|
||||
return wait.IsCompleted
|
||||
? _releaserTask ?? Task.FromResult(CreateReleaser()) // anonymous vs named
|
||||
: wait.ContinueWith((_, state) => (((AsyncLock)state).CreateReleaser()),
|
||||
this, CancellationToken.None,
|
||||
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
|
||||
}
|
||||
|
||||
public IDisposable Lock()
|
||||
{
|
||||
if (_semaphore != null)
|
||||
@@ -168,40 +181,5 @@ namespace Umbraco.Core
|
||||
Dispose(false);
|
||||
}
|
||||
}
|
||||
|
||||
// http://stackoverflow.com/questions/25382583/waiting-on-a-named-semaphore-with-waitone100-vs-waitone0-task-delay100
|
||||
// http://blog.nerdbank.net/2011/07/c-await-for-waithandle.html
|
||||
// F# has a AwaitWaitHandle method that accepts a time out... and seems pretty complex...
|
||||
// version below should be OK
|
||||
|
||||
private static Task WaitOneAsync(WaitHandle handle)
|
||||
{
|
||||
var tcs = new TaskCompletionSource<object>();
|
||||
var callbackHandleInitLock = new object();
|
||||
lock (callbackHandleInitLock)
|
||||
{
|
||||
RegisteredWaitHandle callbackHandle = null;
|
||||
// ReSharper disable once RedundantAssignment
|
||||
callbackHandle = ThreadPool.RegisterWaitForSingleObject(
|
||||
handle,
|
||||
(state, timedOut) =>
|
||||
{
|
||||
tcs.SetResult(null);
|
||||
|
||||
// we take a lock here to make sure the outer method has completed setting the local variable callbackHandle.
|
||||
lock (callbackHandleInitLock)
|
||||
{
|
||||
// ReSharper disable once PossibleNullReferenceException
|
||||
// ReSharper disable once AccessToModifiedClosure
|
||||
callbackHandle.Unregister(null);
|
||||
}
|
||||
},
|
||||
/*state:*/ null,
|
||||
/*millisecondsTimeOutInterval:*/ Timeout.Infinite,
|
||||
/*executeOnlyOnce:*/ true);
|
||||
}
|
||||
|
||||
return tcs.Task;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,17 @@
|
||||
namespace Umbraco.Core.Auditing
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Public method to create new audit trail
|
||||
/// </summary>
|
||||
[Obsolete("Use Umbraco.Core.Services.IAuditService instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static class Audit
|
||||
{
|
||||
public static void Add(AuditTypes type, string comment, int userId, int objectId)
|
||||
public static void Add(Umbraco.Core.Auditing.AuditTypes type, string comment, int userId, int objectId)
|
||||
{
|
||||
AuditTrail.Current.AddEntry(type, comment, userId, objectId);
|
||||
ApplicationContext.Current.Services.AuditService.Add(
|
||||
Enum<Umbraco.Core.Models.AuditType>.Parse(type.ToString()),
|
||||
comment, userId, objectId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Audit implementation
|
||||
/// </summary>
|
||||
internal class AuditTrail
|
||||
{
|
||||
#region Singleton
|
||||
|
||||
private static readonly Lazy<AuditTrail> lazy = new Lazy<AuditTrail>(() => new AuditTrail());
|
||||
|
||||
public static AuditTrail Current { get { return lazy.Value; } }
|
||||
|
||||
private AuditTrail()
|
||||
{
|
||||
WriteProvider = new DataAuditWriteProvider();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private IAuditWriteProvider WriteProvider { get; set; }
|
||||
|
||||
public void AddEntry(AuditTypes type, string comment, int userId, int objectId)
|
||||
{
|
||||
WriteProvider.WriteEntry(objectId, userId, DateTime.Now, type.ToString(), comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
namespace Umbraco.Core.Auditing
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
/// <summary>
|
||||
/// Enums for vailable types of auditing
|
||||
/// </summary>
|
||||
[Obsolete("Use Umbraco.Core.Models.AuditType instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public enum AuditTypes
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
internal class DataAuditWriteProvider : IAuditWriteProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes an audit entry to the underlaying datastore.
|
||||
/// </summary>
|
||||
/// <param name="objectId">Id of the object (Content, ContentType, Media, etc.)</param>
|
||||
/// <param name="userId">Id of the user</param>
|
||||
/// <param name="date">Datestamp</param>
|
||||
/// <param name="header">Audit header</param>
|
||||
/// <param name="comment">Audit comment</param>
|
||||
public void WriteEntry(int objectId, int userId, DateTime date, string header, string comment)
|
||||
{
|
||||
ApplicationContext.Current.DatabaseContext.Database.Insert(new LogDto
|
||||
{
|
||||
Comment = comment,
|
||||
Datestamp = date,
|
||||
Header = header,
|
||||
NodeId = objectId,
|
||||
UserId = userId
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Auditing
|
||||
{
|
||||
internal interface IAuditWriteProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes an audit entry to the underlaying datastore.
|
||||
/// </summary>
|
||||
/// <param name="objectId">Id of the object (Content, ContentType, Media, etc.)</param>
|
||||
/// <param name="userId">Id of the user</param>
|
||||
/// <param name="date">Datestamp</param>
|
||||
/// <param name="header">Audit header</param>
|
||||
/// <param name="comment">Audit comment</param>
|
||||
void WriteEntry(int objectId, int userId, DateTime date, string header, string comment);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,8 @@ namespace Umbraco.Core.Cache
|
||||
public const string MemberBusinessLogicCacheKey = "MemberCacheItem_";
|
||||
|
||||
public const string TemplateFrontEndCacheKey = "template";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
|
||||
|
||||
public const string UserContextCacheKey = "UmbracoUserContext";
|
||||
@@ -45,11 +47,15 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
public const string LanguageCacheKey = "UmbracoLanguageCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
public const string DomainCacheKey = "UmbracoDomainList";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
public const string StylesheetCacheKey = "UmbracoStylesheet";
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty";
|
||||
|
||||
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
|
||||
|
||||
@@ -105,6 +105,9 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
@@ -114,7 +117,10 @@ namespace Umbraco.Core.Cache
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
return value == null || value.GetType().ToString().InvariantEquals(typeName);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
})
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
@@ -124,6 +130,7 @@ namespace Umbraco.Core.Cache
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
@@ -134,7 +141,10 @@ namespace Umbraco.Core.Cache
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
return value == null || value.GetType() == typeOfT;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
})
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
@@ -144,6 +154,7 @@ namespace Umbraco.Core.Cache
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
using (WriteLock)
|
||||
{
|
||||
@@ -156,9 +167,12 @@ namespace Umbraco.Core.Cache
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
if (value == null) return true;
|
||||
return value.GetType() == typeOfT
|
||||
// run predicate on the 'public key' part only, ie without prefix
|
||||
&& predicate(((string)x.Key).Substring(plen), (T)value);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
|
||||
// run predicate on the 'public key' part only, ie without prefix
|
||||
&& predicate(((string) x.Key).Substring(plen), (T) value);
|
||||
}))
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Cache
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
|
||||
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = GetSafeLazy(getCacheItem);
|
||||
@@ -122,7 +122,7 @@ namespace Umbraco.Core.Cache
|
||||
if (eh != null) throw eh.Exception; // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
|
||||
@@ -20,16 +20,22 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
private readonly System.Web.Caching.Cache _cache;
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging
|
||||
/// </summary>
|
||||
internal Guid InstanceId { get; private set; }
|
||||
|
||||
public HttpRuntimeCacheProvider(System.Web.Caching.Cache cache)
|
||||
{
|
||||
_cache = cache;
|
||||
InstanceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
return _cache.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string && ((string) x.Key).StartsWith(prefix));
|
||||
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
@@ -134,6 +140,7 @@ namespace Umbraco.Core.Cache
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
}
|
||||
@@ -184,13 +191,14 @@ namespace Umbraco.Core.Cache
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
if (value == null) return; // do not store null values (backward compat)
|
||||
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,51 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
public interface ICacheProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes all items from the cache.
|
||||
/// </summary>
|
||||
void ClearAllCache();
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the cache, identified by its key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the item.</param>
|
||||
void ClearCacheItem(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type.
|
||||
/// </summary>
|
||||
/// <param name="typeName">The name of the type to remove.</param>
|
||||
/// <remarks>
|
||||
/// <para>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</para>
|
||||
/// <para>Performs a case-sensitive search.</para>
|
||||
/// </remarks>
|
||||
void ClearCacheObjectTypes(string typeName);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items to remove.</typeparam>
|
||||
/// <remarks>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</remarks>
|
||||
void ClearCacheObjectTypes<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type, satisfying a predicate.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items to remove.</typeparam>
|
||||
/// <param name="predicate">The predicate to satisfy.</param>
|
||||
/// <remarks>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</remarks>
|
||||
void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate);
|
||||
|
||||
void ClearCacheByKeySearch(string keyStartsWith);
|
||||
void ClearCacheByKeyExpression(string regexString);
|
||||
|
||||
IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith);
|
||||
IEnumerable<object> GetCacheItemsByKeyExpression(string regexString);
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache refresher that supports refreshing cache based on a custom payload
|
||||
/// </summary>
|
||||
interface IPayloadCacheRefresher : IJsonCacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Refreshes, clears, etc... any cache based on the information provided in the payload
|
||||
/// </summary>
|
||||
/// <param name="payload"></param>
|
||||
void Refresh(object payload);
|
||||
}
|
||||
}
|
||||
@@ -4,17 +4,16 @@ using umbraco.interfaces;
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for json cache refreshers that ensures the correct events are raised when
|
||||
/// cache refreshing occurs.
|
||||
/// Provides a base class for "json" cache refreshers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The real cache refresher type, this is used for raising strongly typed events</typeparam>
|
||||
public abstract class JsonCacheRefresherBase<TInstanceType> : CacheRefresherBase<TInstanceType>, IJsonCacheRefresher
|
||||
where TInstanceType : ICacheRefresher
|
||||
/// <typeparam name="TInstance">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>Ensures that the correct events are raised when cache refreshing occurs.</remarks>
|
||||
public abstract class JsonCacheRefresherBase<TInstance> : CacheRefresherBase<TInstance>, IJsonCacheRefresher
|
||||
where TInstance : ICacheRefresher
|
||||
{
|
||||
|
||||
public virtual void Refresh(string jsonPayload)
|
||||
public virtual void Refresh(string json)
|
||||
{
|
||||
OnCacheUpdated(Instance, new CacheRefresherEventArgs(jsonPayload, MessageType.RefreshByJson));
|
||||
OnCacheUpdated(Instance, new CacheRefresherEventArgs(json, MessageType.RefreshByJson));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Caching;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
@@ -16,12 +17,19 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
internal class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider
|
||||
{
|
||||
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
internal ObjectCache MemoryCache;
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging
|
||||
/// </summary>
|
||||
internal Guid InstanceId { get; private set; }
|
||||
|
||||
public ObjectCacheRuntimeCacheProvider()
|
||||
{
|
||||
MemoryCache = new MemoryCache("in-memory");
|
||||
InstanceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
#region Clear
|
||||
@@ -41,11 +49,14 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
if (MemoryCache[key] == null) return;
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
foreach (var key in MemoryCache
|
||||
@@ -55,7 +66,10 @@ namespace Umbraco.Core.Cache
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
return value == null || value.GetType().ToString().InvariantEquals(typeName);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
@@ -68,6 +82,7 @@ namespace Umbraco.Core.Cache
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
var typeOfT = typeof (T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
@@ -75,7 +90,11 @@ namespace Umbraco.Core.Cache
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
return value == null || value.GetType() == typeOfT;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
@@ -88,6 +107,7 @@ namespace Umbraco.Core.Cache
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
@@ -96,8 +116,11 @@ namespace Umbraco.Core.Cache
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
if (value == null) return true;
|
||||
return value.GetType() == typeOfT
|
||||
&& predicate(x.Key, (T) value);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
|
||||
&& predicate(x.Key, (T)value);
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
@@ -114,7 +137,7 @@ namespace Umbraco.Core.Cache
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
@@ -126,7 +149,7 @@ namespace Umbraco.Core.Cache
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -178,7 +201,7 @@ namespace Umbraco.Core.Cache
|
||||
return GetCacheItem(cacheKey, getCacheItem, null);
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal,CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
// see notes in HttpRuntimeCacheProvider
|
||||
|
||||
@@ -193,6 +216,7 @@ namespace Umbraco.Core.Cache
|
||||
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
//NOTE: This does an add or update
|
||||
MemoryCache.Set(cacheKey, result, policy);
|
||||
}
|
||||
}
|
||||
@@ -219,6 +243,7 @@ namespace Umbraco.Core.Cache
|
||||
if (value == null) return; // do not store null values (backward compat)
|
||||
|
||||
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
|
||||
//NOTE: This does an add or update
|
||||
MemoryCache.Set(cacheKey, result, policy);
|
||||
}
|
||||
|
||||
@@ -239,7 +264,7 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
policy.ChangeMonitors.Add(new HostFileChangeMonitor(dependentFiles.ToList()));
|
||||
}
|
||||
|
||||
|
||||
if (removedCallback != null)
|
||||
{
|
||||
policy.RemovedCallback = arguments =>
|
||||
@@ -270,6 +295,5 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
return policy;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using Umbraco.Core.Sync;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a base class for "payload" cache refreshers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstance">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>Ensures that the correct events are raised when cache refreshing occurs.</remarks>
|
||||
public abstract class PayloadCacheRefresherBase<TInstance> : JsonCacheRefresherBase<TInstance>, IPayloadCacheRefresher
|
||||
where TInstance : ICacheRefresher
|
||||
{
|
||||
protected abstract object Deserialize(string json);
|
||||
|
||||
public override void Refresh(string json)
|
||||
{
|
||||
var payload = Deserialize(json);
|
||||
Refresh(payload);
|
||||
}
|
||||
|
||||
public virtual void Refresh(object payload)
|
||||
{
|
||||
OnCacheUpdated(Instance, new CacheRefresherEventArgs(payload, MessageType.RefreshByPayload));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using umbraco.interfaces;
|
||||
|
||||
@@ -12,13 +13,14 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
internal sealed class CacheRefreshersResolver : LegacyTransientObjectsResolver<CacheRefreshersResolver, ICacheRefresher>
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="refreshers"></param>
|
||||
internal CacheRefreshersResolver(Func<IEnumerable<Type>> refreshers)
|
||||
: base(refreshers)
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="refreshers"></param>
|
||||
internal CacheRefreshersResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> refreshers)
|
||||
: base(serviceProvider, logger, refreshers)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -8,10 +8,13 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal class ClientDependencyConfiguration
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _fileName;
|
||||
|
||||
public ClientDependencyConfiguration()
|
||||
public ClientDependencyConfiguration(ILogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
_logger = logger;
|
||||
_fileName = IOHelper.MapPath(string.Format("{0}/ClientDependency.config", SystemDirectories.Config));
|
||||
}
|
||||
|
||||
@@ -35,13 +38,13 @@ namespace Umbraco.Core.Configuration
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
LogHelper.Info<ClientDependencyConfiguration>(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion));
|
||||
_logger.Info<ClientDependencyConfiguration>(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -174,7 +174,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// We also make sure that the virtual directory (SystemDirectories.Root) is stripped off first, otherwise we'd end up with something
|
||||
/// like "MyVirtualDirectory-Umbraco" instead of just "Umbraco".
|
||||
/// </remarks>
|
||||
internal static string UmbracoMvcArea
|
||||
public static string UmbracoMvcArea
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -242,6 +242,7 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Move these to constants!
|
||||
public const string UmbracoConnectionName = "umbracoDbDSN";
|
||||
public const string UmbracoMigrationName = "Umbraco";
|
||||
|
||||
@@ -420,14 +421,15 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets a value indicating whether the current version of umbraco is configured.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if configured; otherwise, <c>false</c>.</value>
|
||||
public static bool Configured
|
||||
[Obsolete("Do not use this, it is no longer in use and will be removed from the codebase in future versions")]
|
||||
internal static bool Configured
|
||||
{
|
||||
get
|
||||
{
|
||||
try
|
||||
{
|
||||
string configStatus = ConfigurationStatus;
|
||||
string currentVersion = UmbracoVersion.Current.ToString(3);
|
||||
string currentVersion = UmbracoVersion.GetSemanticVersion().ToSemanticString();
|
||||
|
||||
|
||||
if (currentVersion != configStatus)
|
||||
@@ -594,10 +596,7 @@ namespace Umbraco.Core.Configuration
|
||||
[Obsolete("Use Umbraco.Core.Configuration.UmbracoVersion.Current instead", false)]
|
||||
public static string CurrentVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
return UmbracoVersion.Current.ToString(3);
|
||||
}
|
||||
get { return UmbracoVersion.GetSemanticVersion().ToSemanticString(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.IO;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
class GridConfig : IGridConfig
|
||||
{
|
||||
public GridConfig(ILogger logger, IRuntimeCacheProvider runtimeCache, DirectoryInfo appPlugins, DirectoryInfo configFolder, bool isDebug)
|
||||
{
|
||||
EditorsConfig = new GridEditorsConfig(logger, runtimeCache, appPlugins, configFolder, isDebug);
|
||||
}
|
||||
|
||||
public IGridEditorsConfig EditorsConfig { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Manifest;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
class GridEditorsConfig : IGridEditorsConfig
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IRuntimeCacheProvider _runtimeCache;
|
||||
private readonly DirectoryInfo _appPlugins;
|
||||
private readonly DirectoryInfo _configFolder;
|
||||
private readonly bool _isDebug;
|
||||
|
||||
public GridEditorsConfig(ILogger logger, IRuntimeCacheProvider runtimeCache, DirectoryInfo appPlugins, DirectoryInfo configFolder, bool isDebug)
|
||||
{
|
||||
_logger = logger;
|
||||
_runtimeCache = runtimeCache;
|
||||
_appPlugins = appPlugins;
|
||||
_configFolder = configFolder;
|
||||
_isDebug = isDebug;
|
||||
}
|
||||
|
||||
public IEnumerable<IGridEditorConfig> Editors
|
||||
{
|
||||
get
|
||||
{
|
||||
Func<List<GridEditor>> getResult = () =>
|
||||
{
|
||||
var editors = new List<GridEditor>();
|
||||
var gridConfig = Path.Combine(_configFolder.FullName, "grid.editors.config.js");
|
||||
if (File.Exists(gridConfig))
|
||||
{
|
||||
try
|
||||
{
|
||||
var arr = JArray.Parse(File.ReadAllText(gridConfig));
|
||||
//ensure the contents parse correctly to objects
|
||||
var parsed = ManifestParser.GetGridEditors(arr);
|
||||
editors.AddRange(parsed);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<GridEditorsConfig>("Could not parse the contents of grid.editors.config.js into a JSON array", ex);
|
||||
}
|
||||
}
|
||||
|
||||
var parser = new ManifestParser(_appPlugins, _runtimeCache);
|
||||
var builder = new ManifestBuilder(_runtimeCache, parser);
|
||||
foreach (var gridEditor in builder.GridEditors)
|
||||
{
|
||||
//no duplicates! (based on alias)
|
||||
if (editors.Contains(gridEditor) == false)
|
||||
{
|
||||
editors.Add(gridEditor);
|
||||
}
|
||||
}
|
||||
return editors;
|
||||
};
|
||||
|
||||
//cache the result if debugging is disabled
|
||||
var result = _isDebug
|
||||
? getResult()
|
||||
: _runtimeCache.GetCacheItem<List<GridEditor>>(
|
||||
typeof(GridEditorsConfig) + "Editors",
|
||||
() => getResult(),
|
||||
TimeSpan.FromMinutes(10));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
public interface IGridConfig
|
||||
{
|
||||
|
||||
IGridEditorsConfig EditorsConfig { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
public interface IGridEditorConfig
|
||||
{
|
||||
string Name { get; }
|
||||
string Alias { get; }
|
||||
string View { get; }
|
||||
string Render { get; }
|
||||
string Icon { get; }
|
||||
IDictionary<string, object> Config { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Grid
|
||||
{
|
||||
public interface IGridEditorsConfig
|
||||
{
|
||||
IEnumerable<IGridEditorConfig> Editors { get; }
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,13 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration.BaseRest;
|
||||
using Umbraco.Core.Configuration.Dashboard;
|
||||
using Umbraco.Core.Configuration.Grid;
|
||||
using Umbraco.Core.Configuration.UmbracoSettings;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -67,6 +70,7 @@ namespace Umbraco.Core.Configuration
|
||||
private IDashboardSection _dashboardSection;
|
||||
private IUmbracoSettingsSection _umbracoSettings;
|
||||
private IBaseRestSection _baseRestExtensions;
|
||||
private IGridConfig _gridConfig;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IDashboardSection
|
||||
@@ -83,14 +87,20 @@ namespace Umbraco.Core.Configuration
|
||||
return _dashboardSection;
|
||||
}
|
||||
|
||||
//ONLY for unit testing
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
internal void SetDashboardSettings(IDashboardSection value)
|
||||
{
|
||||
_dashboardSection = value;
|
||||
}
|
||||
|
||||
//ONLY for unit testing
|
||||
internal void SetUmbracoSettings(IUmbracoSettingsSection value)
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetUmbracoSettings(IUmbracoSettingsSection value)
|
||||
{
|
||||
_umbracoSettings = value;
|
||||
}
|
||||
@@ -110,7 +120,10 @@ namespace Umbraco.Core.Configuration
|
||||
return _umbracoSettings;
|
||||
}
|
||||
|
||||
//ONLY for unit testing
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetBaseRestExtensions(IBaseRestSection value)
|
||||
{
|
||||
_baseRestExtensions = value;
|
||||
@@ -131,6 +144,28 @@ namespace Umbraco.Core.Configuration
|
||||
return _baseRestExtensions;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Only for testing
|
||||
/// </summary>
|
||||
/// <param name="value"></param>
|
||||
public void SetGridConfig(IGridConfig value)
|
||||
{
|
||||
_gridConfig = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IGridConfig
|
||||
/// </summary>
|
||||
public IGridConfig GridConfig(ILogger logger, IRuntimeCacheProvider runtimeCache, DirectoryInfo appPlugins, DirectoryInfo configFolder, bool isDebug)
|
||||
{
|
||||
if (_gridConfig == null)
|
||||
{
|
||||
_gridConfig = new GridConfig(logger, runtimeCache, appPlugins, configFolder, isDebug);
|
||||
}
|
||||
|
||||
return _gridConfig;
|
||||
}
|
||||
|
||||
//TODO: Add other configurations here !
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public interface ITemplatesSection : IUmbracoConfigurationSection
|
||||
{
|
||||
@@ -8,6 +10,7 @@
|
||||
|
||||
RenderingEngine DefaultRenderingEngine { get; }
|
||||
|
||||
[Obsolete("This has no affect and will be removed in future versions")]
|
||||
bool EnableTemplateFolders { get; }
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@
|
||||
bool DisableFindContentByIdPath { get; }
|
||||
|
||||
string UrlProviderMode { get; }
|
||||
|
||||
string UmbracoApplicationUrl { get; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Configuration;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
@@ -40,6 +41,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This has no affect and will be removed in future versions")]
|
||||
[ConfigurationProperty("enableTemplateFolders")]
|
||||
internal InnerTextConfigurationElement<bool> EnableTemplateFolders
|
||||
{
|
||||
@@ -67,6 +69,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return DefaultRenderingEngine; }
|
||||
}
|
||||
|
||||
[Obsolete("This has no affect and will be removed in future versions")]
|
||||
bool ITemplatesSection.EnableTemplateFolders
|
||||
{
|
||||
get { return EnableTemplateFolders; }
|
||||
|
||||
@@ -30,8 +30,13 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
[ConfigurationProperty("urlProviderMode", DefaultValue = "AutoLegacy")]
|
||||
public string UrlProviderMode
|
||||
{
|
||||
get { return (string)base["urlProviderMode"]; }
|
||||
get { return (string) base["urlProviderMode"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("umbracoApplicationUrl", DefaultValue = null)]
|
||||
public string UmbracoApplicationUrl
|
||||
{
|
||||
get { return (string)base["umbracoApplicationUrl"]; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using Semver;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.2.6");
|
||||
private static readonly Version Version = new Version("7.3.0");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
@@ -28,5 +29,15 @@ namespace Umbraco.Core.Configuration
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
public static string AssemblyVersion { get { return new AssemblyName(typeof(ActionsResolver).Assembly.FullName).Version.ToString(); } }
|
||||
|
||||
public static SemVersion GetSemanticVersion()
|
||||
{
|
||||
return new SemVersion(
|
||||
Current.Major,
|
||||
Current.Minor,
|
||||
Current.Build,
|
||||
CurrentComment.IsNullOrWhiteSpace() ? null : CurrentComment,
|
||||
Current.Revision > 0 ? Current.Revision.ToInvariantString() : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,12 +78,12 @@
|
||||
/// </summary>
|
||||
public const string Dictionary = "dictionary";
|
||||
|
||||
//TODO: Fill in the rest!
|
||||
public const string Stylesheets = "stylesheets";
|
||||
|
||||
/// <summary>
|
||||
/// alias for the media tree.
|
||||
/// alias for the template tree.
|
||||
/// </summary>
|
||||
public const string Templates = "template";
|
||||
public const string Templates = "templates";
|
||||
|
||||
public const string RelationTypes = "relationTypes";
|
||||
|
||||
@@ -91,6 +91,7 @@
|
||||
|
||||
public const string Languages = "languages";
|
||||
|
||||
//TODO: Fill in the rest!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,26 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static class Conventions
|
||||
{
|
||||
public static class PublicAccess
|
||||
{
|
||||
public const string MemberUsernameRuleType = "MemberUsername";
|
||||
public const string MemberRoleRuleType = "MemberRole";
|
||||
|
||||
[Obsolete("No longer supported, this is here for backwards compatibility only")]
|
||||
public const string MemberIdRuleType = "MemberId";
|
||||
[Obsolete("No longer supported, this is here for backwards compatibility only")]
|
||||
public const string MemberGroupIdRuleType = "MemberGroupId";
|
||||
}
|
||||
|
||||
public static class Localization
|
||||
{
|
||||
/// <summary>
|
||||
/// The root id for all top level dictionary items
|
||||
/// </summary>
|
||||
[Obsolete("There is no dictionary root item id anymore, it is simply null")]
|
||||
public const string DictionaryItemRootId = "41c7638d-f529-4bff-853e-59a0c2fb1bde";
|
||||
}
|
||||
|
||||
public static class DataTypes
|
||||
{
|
||||
public const string ListViewPrefix = "List View - ";
|
||||
@@ -284,7 +304,7 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines the alias identifiers for Umbraco relation types.
|
||||
/// Defines the alias identifiers for built-in Umbraco relation types.
|
||||
/// </summary>
|
||||
public static class RelationTypes
|
||||
{
|
||||
@@ -297,6 +317,16 @@ namespace Umbraco.Core
|
||||
/// ContentType alias for default relation type "Relate Document On Copy".
|
||||
/// </summary>
|
||||
public const string RelateDocumentOnCopyAlias = "relateDocumentOnCopy";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType name for default relation type "Relate Parent Document On Delete".
|
||||
/// </summary>
|
||||
public const string RelateParentDocumentOnDeleteName = "Relate Parent Document On Delete";
|
||||
|
||||
/// <summary>
|
||||
/// ContentType alias for default relation type "Relate Parent Document On Delete".
|
||||
/// </summary>
|
||||
public const string RelateParentDocumentOnDeleteAlias = "relateParentDocumentOnDelete";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,97 @@
|
||||
namespace Umbraco.Core
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the identifiers for Umbraco object types as constants for easy centralized access/management.
|
||||
/// </summary>
|
||||
public static class ObjectTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Guid for a Content Item object.
|
||||
/// </summary>
|
||||
public const string ContentItem = "10E2B09F-C28B-476D-B77A-AA686435E44A";
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the identifiers for Umbraco object types as constants for easy centralized access/management.
|
||||
/// </summary>
|
||||
public static class ObjectTypes
|
||||
{
|
||||
/// <summary>
|
||||
/// Guid for a Content Item object.
|
||||
/// </summary>
|
||||
public const string ContentItem = "10E2B09F-C28B-476D-B77A-AA686435E44A";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Content Item Type object.
|
||||
/// </summary>
|
||||
public const string ContentItemType = "7A333C54-6F43-40A4-86A2-18688DC7E532";
|
||||
/// <summary>
|
||||
/// Guid for a Content Item Type object.
|
||||
/// </summary>
|
||||
public const string ContentItemType = "7A333C54-6F43-40A4-86A2-18688DC7E532";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Content Recycle Bin.
|
||||
/// </summary>
|
||||
public const string ContentRecycleBin = "01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8";
|
||||
/// <summary>
|
||||
/// Guid for the Content Recycle Bin.
|
||||
/// </summary>
|
||||
public const string ContentRecycleBin = "01BB7FF2-24DC-4C0C-95A2-C24EF72BBAC8";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a DataType object.
|
||||
/// </summary>
|
||||
public const string DataType = "30A2A501-1978-4DDB-A57B-F7EFED43BA3C";
|
||||
/// <summary>
|
||||
/// Guid for a DataType object.
|
||||
/// </summary>
|
||||
public const string DataType = "30A2A501-1978-4DDB-A57B-F7EFED43BA3C";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document object.
|
||||
/// </summary>
|
||||
public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
|
||||
/// <summary>
|
||||
/// Guid for a Document object.
|
||||
/// </summary>
|
||||
public const string Document = "C66BA18E-EAF3-4CFF-8A22-41B16D66A972";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document Type object.
|
||||
/// </summary>
|
||||
public const string DocumentType = "A2CB7800-F571-4787-9638-BC48539A0EFB";
|
||||
/// <summary>
|
||||
/// Guid for a Document Type object.
|
||||
/// </summary>
|
||||
public const string DocumentType = "A2CB7800-F571-4787-9638-BC48539A0EFB";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Media object.
|
||||
/// </summary>
|
||||
public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C";
|
||||
/// <summary>
|
||||
/// Guid for a Media object.
|
||||
/// </summary>
|
||||
public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Media Recycle Bin.
|
||||
/// </summary>
|
||||
public const string MediaRecycleBin = "CF3D8E34-1C1C-41e9-AE56-878B57B32113";
|
||||
/// <summary>
|
||||
/// Guid for the Media Recycle Bin.
|
||||
/// </summary>
|
||||
public const string MediaRecycleBin = "CF3D8E34-1C1C-41e9-AE56-878B57B32113";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Media Type object.
|
||||
/// </summary>
|
||||
public const string MediaType = "4EA4382B-2F5A-4C2B-9587-AE9B3CF3602E";
|
||||
/// <summary>
|
||||
/// Guid for a Media Type object.
|
||||
/// </summary>
|
||||
public const string MediaType = "4EA4382B-2F5A-4C2B-9587-AE9B3CF3602E";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member object.
|
||||
/// </summary>
|
||||
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
|
||||
/// <summary>
|
||||
/// Guid for a Member object.
|
||||
/// </summary>
|
||||
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Group object.
|
||||
/// </summary>
|
||||
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
|
||||
/// <summary>
|
||||
/// Guid for a Member Group object.
|
||||
/// </summary>
|
||||
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Type object.
|
||||
/// </summary>
|
||||
public const string MemberType = "9B5416FB-E72F-45A9-A07B-5A9A2709CE43";
|
||||
/// <summary>
|
||||
/// Guid for a Member Type object.
|
||||
/// </summary>
|
||||
public const string MemberType = "9B5416FB-E72F-45A9-A07B-5A9A2709CE43";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Stylesheet object.
|
||||
/// </summary>
|
||||
public const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840";
|
||||
/// <summary>
|
||||
/// Guid for a Stylesheet object.
|
||||
/// </summary>
|
||||
[Obsolete("This no longer exists in the database")]
|
||||
public const string Stylesheet = "9F68DA4F-A3A8-44C2-8226-DCBD125E4840";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the System Root.
|
||||
/// </summary>
|
||||
public const string SystemRoot = "EA7D8624-4CFE-4578-A871-24AA946BF34D";
|
||||
[Obsolete("This no longer exists in the database")]
|
||||
internal const string StylesheetProperty = "5555da4f-a123-42b2-4488-dcdfb25e4111";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Template object.
|
||||
/// </summary>
|
||||
public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D";
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Guid for the System Root.
|
||||
/// </summary>
|
||||
public const string SystemRoot = "EA7D8624-4CFE-4578-A871-24AA946BF34D";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Template object.
|
||||
/// </summary>
|
||||
public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Lock object.
|
||||
/// </summary>
|
||||
public const string LockObject = "87A9F1FF-B1E4-4A25-BABB-465A4A47EC41";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,8 @@
|
||||
public const int DefaultMediaListViewDataTypeId = -96;
|
||||
public const int DefaultMembersListViewDataTypeId = -97;
|
||||
|
||||
// identifiers for lock objects
|
||||
public const int ServersLock = -331;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,5 +18,30 @@
|
||||
public const string AuthCookieName = "UMB_UCONTEXT";
|
||||
|
||||
}
|
||||
|
||||
public static class Security
|
||||
{
|
||||
|
||||
public const string BackOfficeAuthenticationType = "UmbracoBackOffice";
|
||||
public const string BackOfficeExternalAuthenticationType = "UmbracoExternalCookie";
|
||||
public const string BackOfficeExternalCookieName = "UMB_EXTLOGIN";
|
||||
public const string BackOfficeTokenAuthenticationType = "UmbracoBackOfficeToken";
|
||||
public const string BackOfficeTwoFactorAuthenticationType = "UmbracoTwoFactorCookie";
|
||||
|
||||
/// <summary>
|
||||
/// The prefix used for external identity providers for their authentication type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default we don't want to interfere with front-end external providers and their default setup, for back office the
|
||||
/// providers need to be setup differently and each auth type for the back office will be prefixed with this value
|
||||
/// </remarks>
|
||||
public const string BackOfficeExternalAuthenticationTypePrefix = "Umbraco.";
|
||||
|
||||
public const string StartContentNodeIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/startcontentnode";
|
||||
public const string StartMediaNodeIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/startmedianode";
|
||||
public const string AllowedApplicationsClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/allowedapp";
|
||||
public const string SessionIdClaimType = "http://umbraco.org/2015/02/identity/claims/backoffice/sessionid";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+320
-151
@@ -2,10 +2,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core.Cache;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Exceptions;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Mapping;
|
||||
@@ -32,101 +35,165 @@ using MigrationsVersionFourNineZero = Umbraco.Core.Persistence.Migrations.Upgrad
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This does not provide any startup functionality relating to web objects
|
||||
/// </remarks>
|
||||
public class CoreBootManager : IBootManager
|
||||
{
|
||||
|
||||
private DisposableTimer _timer;
|
||||
private bool _isInitialized = false;
|
||||
private bool _isStarted = false;
|
||||
private bool _isComplete = false;
|
||||
/// A bootstrapper for the Umbraco application which initializes all objects for the Core of the application
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This does not provide any startup functionality relating to web objects
|
||||
/// </remarks>
|
||||
public class CoreBootManager : IBootManager
|
||||
{
|
||||
protected ProfilingLogger ProfilingLogger { get; private set; }
|
||||
private DisposableTimer _timer;
|
||||
private bool _isInitialized = false;
|
||||
private bool _isStarted = false;
|
||||
private bool _isComplete = false;
|
||||
private readonly IServiceProvider _serviceProvider = new ActivatorServiceProvider();
|
||||
private readonly UmbracoApplicationBase _umbracoApplication;
|
||||
protected ApplicationContext ApplicationContext { get; set; }
|
||||
protected CacheHelper ApplicationCache { get; set; }
|
||||
protected ApplicationContext ApplicationContext { get; private set; }
|
||||
protected CacheHelper ApplicationCache { get; private set; }
|
||||
protected PluginManager PluginManager { get; private set; }
|
||||
|
||||
protected UmbracoApplicationBase UmbracoApplication
|
||||
{
|
||||
get { return _umbracoApplication; }
|
||||
}
|
||||
protected UmbracoApplicationBase UmbracoApplication
|
||||
{
|
||||
get { return _umbracoApplication; }
|
||||
}
|
||||
|
||||
public CoreBootManager(UmbracoApplicationBase umbracoApplication)
|
||||
{
|
||||
protected IServiceProvider ServiceProvider
|
||||
{
|
||||
get { return _serviceProvider; }
|
||||
}
|
||||
|
||||
public CoreBootManager(UmbracoApplicationBase umbracoApplication)
|
||||
{
|
||||
if (umbracoApplication == null) throw new ArgumentNullException("umbracoApplication");
|
||||
_umbracoApplication = umbracoApplication;
|
||||
}
|
||||
|
||||
public virtual IBootManager Initialize()
|
||||
{
|
||||
if (_isInitialized)
|
||||
throw new InvalidOperationException("The boot manager has already been initialized");
|
||||
internal CoreBootManager(UmbracoApplicationBase umbracoApplication, ProfilingLogger logger)
|
||||
{
|
||||
if (umbracoApplication == null) throw new ArgumentNullException("umbracoApplication");
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
_umbracoApplication = umbracoApplication;
|
||||
ProfilingLogger = logger;
|
||||
}
|
||||
|
||||
InitializeProfilerResolver();
|
||||
public virtual IBootManager Initialize()
|
||||
{
|
||||
if (_isInitialized)
|
||||
throw new InvalidOperationException("The boot manager has already been initialized");
|
||||
|
||||
_timer = DisposableTimer.TraceDuration<CoreBootManager>("Umbraco application starting", "Umbraco application startup complete");
|
||||
|
||||
CreateApplicationCache();
|
||||
InitializeLoggerResolver();
|
||||
InitializeProfilerResolver();
|
||||
|
||||
ProfilingLogger = ProfilingLogger?? new ProfilingLogger(LoggerResolver.Current.Logger, ProfilerResolver.Current.Profiler);
|
||||
|
||||
_timer = ProfilingLogger.TraceDuration<CoreBootManager>(
|
||||
string.Format("Umbraco {0} application starting on {1}", UmbracoVersion.GetSemanticVersion().ToSemanticString(), NetworkHelper.MachineName),
|
||||
"Umbraco application startup complete");
|
||||
|
||||
ApplicationCache = CreateApplicationCache();
|
||||
|
||||
//create and set the plugin manager (I'd much prefer to not use this singleton anymore but many things are using it unfortunately and
|
||||
// the way that it is setup, there must only ever be one per app so without IoC it would be hard to make this not a singleton)
|
||||
PluginManager = new PluginManager(ServiceProvider, ApplicationCache.RuntimeCache, ProfilingLogger);
|
||||
PluginManager.Current = PluginManager;
|
||||
|
||||
//Create the legacy prop-eds mapping
|
||||
LegacyPropertyEditorIdToAliasConverter.CreateMappingsForCoreEditors();
|
||||
LegacyParameterEditorAliasConverter.CreateMappingsForCoreEditors();
|
||||
|
||||
//create database and service contexts for the app context
|
||||
var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName);
|
||||
Database.Mapper = new PetaPocoMapper();
|
||||
var dbContext = new DatabaseContext(dbFactory);
|
||||
var serviceContext = new ServiceContext(
|
||||
new PetaPocoUnitOfWorkProvider(dbFactory),
|
||||
new FileUnitOfWorkProvider(),
|
||||
new PublishingStrategy(),
|
||||
ApplicationCache);
|
||||
//create database and service contexts for the app context
|
||||
var dbFactory = new DefaultDatabaseFactory(GlobalSettings.UmbracoConnectionName, ProfilingLogger.Logger);
|
||||
Database.Mapper = new PetaPocoMapper();
|
||||
|
||||
CreateApplicationContext(dbContext, serviceContext);
|
||||
|
||||
InitializeApplicationEventsResolver();
|
||||
|
||||
InitializeResolvers();
|
||||
var dbContext = new DatabaseContext(
|
||||
dbFactory,
|
||||
ProfilingLogger.Logger,
|
||||
SqlSyntaxProviders.CreateDefault(ProfilingLogger.Logger));
|
||||
|
||||
//initialize the DatabaseContext
|
||||
dbContext.Initialize();
|
||||
|
||||
//get the service context
|
||||
var serviceContext = CreateServiceContext(dbContext, dbFactory);
|
||||
|
||||
//set property and singleton from response
|
||||
ApplicationContext.Current = ApplicationContext = CreateApplicationContext(dbContext, serviceContext);
|
||||
|
||||
InitializeApplicationEventsResolver();
|
||||
|
||||
InitializeResolvers();
|
||||
|
||||
InitializeModelMappers();
|
||||
|
||||
//now we need to call the initialize methods
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x => x.OnApplicationInitialized(UmbracoApplication, ApplicationContext));
|
||||
using (ProfilingLogger.DebugDuration<CoreBootManager>(
|
||||
string.Format("Executing {0} IApplicationEventHandler.OnApplicationInitialized", ApplicationEventsResolver.Current.ApplicationEventHandlers.Count()),
|
||||
"Finished executing IApplicationEventHandler.OnApplicationInitialized"))
|
||||
{
|
||||
//now we need to call the initialize methods
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
x.OnApplicationInitialized(UmbracoApplication, ApplicationContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ProfilingLogger.Logger.Error<CoreBootManager>("An error occurred running OnApplicationInitialized for handler " + x.GetType(), ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_isInitialized = true;
|
||||
_isInitialized = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and assigns the application context singleton
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="serviceContext"></param>
|
||||
protected virtual void CreateApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext)
|
||||
{
|
||||
//create the ApplicationContext
|
||||
ApplicationContext = ApplicationContext.Current = new ApplicationContext(dbContext, serviceContext, ApplicationCache);
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and assigns the ApplicationCache based on a new instance of System.Web.Caching.Cache
|
||||
/// Creates and returns the service context for the app
|
||||
/// </summary>
|
||||
protected virtual void CreateApplicationCache()
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="dbFactory"></param>
|
||||
/// <returns></returns>
|
||||
protected virtual ServiceContext CreateServiceContext(DatabaseContext dbContext, IDatabaseFactory dbFactory)
|
||||
{
|
||||
//default transient factory
|
||||
var msgFactory = new TransientMessagesFactory();
|
||||
return new ServiceContext(
|
||||
new RepositoryFactory(ApplicationCache, ProfilingLogger.Logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()),
|
||||
new PetaPocoUnitOfWorkProvider(dbFactory),
|
||||
new FileUnitOfWorkProvider(),
|
||||
new PublishingStrategy(msgFactory, ProfilingLogger.Logger),
|
||||
ApplicationCache,
|
||||
ProfilingLogger.Logger,
|
||||
msgFactory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns the application context for the app
|
||||
/// </summary>
|
||||
/// <param name="dbContext"></param>
|
||||
/// <param name="serviceContext"></param>
|
||||
protected virtual ApplicationContext CreateApplicationContext(DatabaseContext dbContext, ServiceContext serviceContext)
|
||||
{
|
||||
//create the ApplicationContext
|
||||
return new ApplicationContext(dbContext, serviceContext, ApplicationCache, ProfilingLogger);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and returns the CacheHelper for the app
|
||||
/// </summary>
|
||||
protected virtual CacheHelper CreateApplicationCache()
|
||||
{
|
||||
var cacheHelper = new CacheHelper(
|
||||
new ObjectCacheRuntimeCacheProvider(),
|
||||
new StaticCacheProvider(),
|
||||
//we have no request based cache when not running in web-based context
|
||||
new NullCacheProvider());
|
||||
new ObjectCacheRuntimeCacheProvider(),
|
||||
new StaticCacheProvider(),
|
||||
//we have no request based cache when not running in web-based context
|
||||
new NullCacheProvider());
|
||||
|
||||
ApplicationCache = cacheHelper;
|
||||
return cacheHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -147,18 +214,31 @@ namespace Umbraco.Core
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special method to initialize the LoggerResolver
|
||||
/// </summary>
|
||||
protected virtual void InitializeLoggerResolver()
|
||||
{
|
||||
LoggerResolver.Current = new LoggerResolver(ProfilingLogger == null ? Logger.CreateWithDefaultLog4NetConfiguration() : ProfilingLogger.Logger)
|
||||
{
|
||||
//This is another special resolver that needs to be resolvable before resolution is frozen
|
||||
//since it is used for profiling the application startup
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Special method to initialize the ProfilerResolver
|
||||
/// </summary>
|
||||
protected virtual void InitializeProfilerResolver()
|
||||
{
|
||||
//By default we'll initialize the Log profiler (in the web project, we'll override with the web profiler)
|
||||
ProfilerResolver.Current = new ProfilerResolver(new LogProfiler())
|
||||
{
|
||||
//This is another special resolver that needs to be resolvable before resolution is frozen
|
||||
//since it is used for profiling the application startup
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
ProfilerResolver.Current = new ProfilerResolver(ProfilingLogger == null ? new LogProfiler(LoggerResolver.Current.Logger) : ProfilingLogger.Profiler)
|
||||
{
|
||||
//This is another special resolver that needs to be resolvable before resolution is frozen
|
||||
//since it is used for profiling the application startup
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -173,7 +253,9 @@ namespace Umbraco.Core
|
||||
//ApplicationStartupHandler.RegisterHandlers();
|
||||
//... and set the special flag to let us resolve before frozen resolution
|
||||
ApplicationEventsResolver.Current = new ApplicationEventsResolver(
|
||||
PluginManager.Current.ResolveApplicationStartupHandlers())
|
||||
ServiceProvider,
|
||||
ProfilingLogger.Logger,
|
||||
PluginManager.ResolveApplicationStartupHandlers())
|
||||
{
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
@@ -187,49 +269,90 @@ namespace Umbraco.Core
|
||||
/// <param name="rootPath">Absolute</param>
|
||||
protected virtual void InitializeApplicationRootPath(string rootPath)
|
||||
{
|
||||
Umbraco.Core.IO.IOHelper.SetRootDirectory(rootPath);
|
||||
IOHelper.SetRootDirectory(rootPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires after initialization and calls the callback to allow for customizations to occur &
|
||||
/// <summary>
|
||||
/// Fires after initialization and calls the callback to allow for customizations to occur &
|
||||
/// Ensure that the OnApplicationStarting methods of the IApplicationEvents are called
|
||||
/// </summary>
|
||||
/// <param name="afterStartup"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IBootManager Startup(Action<ApplicationContext> afterStartup)
|
||||
{
|
||||
if (_isStarted)
|
||||
throw new InvalidOperationException("The boot manager has already been initialized");
|
||||
/// </summary>
|
||||
/// <param name="afterStartup"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IBootManager Startup(Action<ApplicationContext> afterStartup)
|
||||
{
|
||||
if (_isStarted)
|
||||
throw new InvalidOperationException("The boot manager has already been initialized");
|
||||
|
||||
//call OnApplicationStarting of each application events handler
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x => x.OnApplicationStarting(UmbracoApplication, ApplicationContext));
|
||||
using (ProfilingLogger.DebugDuration<CoreBootManager>(
|
||||
string.Format("Executing {0} IApplicationEventHandler.OnApplicationStarting", ApplicationEventsResolver.Current.ApplicationEventHandlers.Count()),
|
||||
"Finished executing IApplicationEventHandler.OnApplicationStarting"))
|
||||
{
|
||||
//call OnApplicationStarting of each application events handler
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
x.OnApplicationStarting(UmbracoApplication, ApplicationContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ProfilingLogger.Logger.Error<CoreBootManager>("An error occurred running OnApplicationStarting for handler " + x.GetType(), ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (afterStartup != null)
|
||||
if (afterStartup != null)
|
||||
{
|
||||
afterStartup(ApplicationContext.Current);
|
||||
}
|
||||
|
||||
_isStarted = true;
|
||||
_isStarted = true;
|
||||
|
||||
return this;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires after startup and calls the callback once customizations are locked
|
||||
/// </summary>
|
||||
/// <param name="afterComplete"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IBootManager Complete(Action<ApplicationContext> afterComplete)
|
||||
{
|
||||
if (_isComplete)
|
||||
throw new InvalidOperationException("The boot manager has already been completed");
|
||||
|
||||
FreezeResolution();
|
||||
/// <summary>
|
||||
/// Fires after startup and calls the callback once customizations are locked
|
||||
/// </summary>
|
||||
/// <param name="afterComplete"></param>
|
||||
/// <returns></returns>
|
||||
public virtual IBootManager Complete(Action<ApplicationContext> afterComplete)
|
||||
{
|
||||
if (_isComplete)
|
||||
throw new InvalidOperationException("The boot manager has already been completed");
|
||||
|
||||
//call OnApplicationStarting of each application events handler
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x => x.OnApplicationStarted(UmbracoApplication, ApplicationContext));
|
||||
FreezeResolution();
|
||||
|
||||
//Here we need to make sure the db can be connected to
|
||||
EnsureDatabaseConnection();
|
||||
|
||||
|
||||
//This is a special case for the user service, we need to tell it if it's an upgrade, if so we need to ensure that
|
||||
// exceptions are bubbled up if a user is attempted to be persisted during an upgrade (i.e. when they auth to login)
|
||||
((UserService) ApplicationContext.Services.UserService).IsUpgrading = true;
|
||||
|
||||
|
||||
using (ProfilingLogger.DebugDuration<CoreBootManager>(
|
||||
string.Format("Executing {0} IApplicationEventHandler.OnApplicationStarted", ApplicationEventsResolver.Current.ApplicationEventHandlers.Count()),
|
||||
"Finished executing IApplicationEventHandler.OnApplicationStarted"))
|
||||
{
|
||||
//call OnApplicationStarting of each application events handler
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x =>
|
||||
{
|
||||
try
|
||||
{
|
||||
x.OnApplicationStarted(UmbracoApplication, ApplicationContext);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
ProfilingLogger.Logger.Error<CoreBootManager>("An error occurred running OnApplicationStarted for handler " + x.GetType(), ex);
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//Now, startup all of our legacy startup handler
|
||||
ApplicationEventsResolver.Current.InstantiateLegacyStartupHandlers();
|
||||
@@ -239,16 +362,46 @@ namespace Umbraco.Core
|
||||
afterComplete(ApplicationContext.Current);
|
||||
}
|
||||
|
||||
_isComplete = true;
|
||||
_isComplete = true;
|
||||
|
||||
// we're ready to serve content!
|
||||
ApplicationContext.IsReady = true;
|
||||
|
||||
//stop the timer and log the output
|
||||
_timer.Dispose();
|
||||
return this;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We cannot continue if the db cannot be connected to
|
||||
/// </summary>
|
||||
private void EnsureDatabaseConnection()
|
||||
{
|
||||
if (ApplicationContext.IsConfigured == false) return;
|
||||
if (ApplicationContext.DatabaseContext.IsDatabaseConfigured == false) return;
|
||||
|
||||
//try now
|
||||
if (ApplicationContext.DatabaseContext.CanConnect)
|
||||
return;
|
||||
|
||||
var currentTry = 0;
|
||||
while (currentTry < 5)
|
||||
{
|
||||
//first wait, then retry
|
||||
Thread.Sleep(1000);
|
||||
|
||||
if (ApplicationContext.DatabaseContext.CanConnect)
|
||||
break;
|
||||
|
||||
currentTry++;
|
||||
}
|
||||
|
||||
if (currentTry == 5)
|
||||
{
|
||||
throw new UmbracoStartupFailedException("Umbraco cannot start. A connection string is configured but the Umbraco cannot connect to the database.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freeze resolution to not allow Resolvers to be modified
|
||||
/// </summary>
|
||||
@@ -256,21 +409,22 @@ namespace Umbraco.Core
|
||||
{
|
||||
Resolution.Freeze();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create the resolvers
|
||||
/// </summary>
|
||||
protected virtual void InitializeResolvers()
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Create the resolvers
|
||||
/// </summary>
|
||||
protected virtual void InitializeResolvers()
|
||||
{
|
||||
var builder = new ManifestBuilder(
|
||||
ApplicationCache.RuntimeCache,
|
||||
new ManifestParser(new DirectoryInfo(IOHelper.MapPath("~/App_Plugins")), ApplicationCache.RuntimeCache));
|
||||
|
||||
PropertyEditorResolver.Current = new PropertyEditorResolver(() => PluginManager.Current.ResolvePropertyEditors(), builder);
|
||||
ParameterEditorResolver.Current = new ParameterEditorResolver(() => PluginManager.Current.ResolveParameterEditors(), builder);
|
||||
PropertyEditorResolver.Current = new PropertyEditorResolver(ServiceProvider, ProfilingLogger.Logger, () => PluginManager.ResolvePropertyEditors(), builder);
|
||||
ParameterEditorResolver.Current = new ParameterEditorResolver(ServiceProvider, ProfilingLogger.Logger, () => PluginManager.ResolveParameterEditors(), builder);
|
||||
|
||||
//setup the validators resolver with our predefined validators
|
||||
ValidatorsResolver.Current = new ValidatorsResolver(new[]
|
||||
ValidatorsResolver.Current = new ValidatorsResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger, new[]
|
||||
{
|
||||
new Lazy<Type>(() => typeof (RequiredManifestValueValidator)),
|
||||
new Lazy<Type>(() => typeof (RegexValidator)),
|
||||
@@ -279,65 +433,80 @@ namespace Umbraco.Core
|
||||
new Lazy<Type>(() => typeof (IntegerValidator)),
|
||||
});
|
||||
|
||||
//by default we'll use the standard configuration based sync
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
|
||||
new ConfigServerRegistrar());
|
||||
//by default we'll use the db server registrar unless the developer has the legacy
|
||||
// dist calls enabled, in which case we'll use the config server registrar
|
||||
if (UmbracoConfig.For.UmbracoSettings().DistributedCall.Enabled)
|
||||
{
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(new ConfigServerRegistrar());
|
||||
}
|
||||
else
|
||||
{
|
||||
ServerRegistrarResolver.Current = new ServerRegistrarResolver(
|
||||
new DatabaseServerRegistrar(
|
||||
new Lazy<IServerRegistrationService>(() => ApplicationContext.Services.ServerRegistrationService),
|
||||
new DatabaseServerRegistrarOptions()));
|
||||
}
|
||||
|
||||
|
||||
//by default (outside of the web) we'll use the default server messenger without
|
||||
//supplying a username/password, this will automatically disable distributed calls
|
||||
// .. we'll override this in the WebBootManager
|
||||
//by default we'll use the database server messenger with default options (no callbacks),
|
||||
// this will be overridden in the web startup
|
||||
ServerMessengerResolver.Current = new ServerMessengerResolver(
|
||||
new DefaultServerMessenger());
|
||||
new DatabaseServerMessenger(ApplicationContext, true, new DatabaseServerMessengerOptions()));
|
||||
|
||||
MappingResolver.Current = new MappingResolver(
|
||||
() => PluginManager.Current.ResolveAssignedMapperTypes());
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolveAssignedMapperTypes());
|
||||
|
||||
RepositoryResolver.Current = new RepositoryResolver(
|
||||
new RepositoryFactory(ApplicationCache));
|
||||
|
||||
//RepositoryResolver.Current = new RepositoryResolver(
|
||||
// new RepositoryFactory(ApplicationCache));
|
||||
|
||||
SqlSyntaxProvidersResolver.Current = new SqlSyntaxProvidersResolver(
|
||||
new[] { typeof(MySqlSyntaxProvider), typeof(SqlCeSyntaxProvider), typeof(SqlServerSyntaxProvider) })
|
||||
{
|
||||
CanResolveBeforeFrozen = true
|
||||
};
|
||||
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolveCacheRefreshers());
|
||||
|
||||
CacheRefreshersResolver.Current = new CacheRefreshersResolver(
|
||||
() => PluginManager.Current.ResolveCacheRefreshers());
|
||||
DataTypesResolver.Current = new DataTypesResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolveDataTypes());
|
||||
|
||||
DataTypesResolver.Current = new DataTypesResolver(
|
||||
() => PluginManager.Current.ResolveDataTypes());
|
||||
MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolveMacroRenderings());
|
||||
|
||||
MacroFieldEditorsResolver.Current = new MacroFieldEditorsResolver(
|
||||
() => PluginManager.Current.ResolveMacroRenderings());
|
||||
PackageActionsResolver.Current = new PackageActionsResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolvePackageActions());
|
||||
|
||||
PackageActionsResolver.Current = new PackageActionsResolver(
|
||||
() => PluginManager.Current.ResolvePackageActions());
|
||||
|
||||
ActionsResolver.Current = new ActionsResolver(
|
||||
() => PluginManager.Current.ResolveActions());
|
||||
ActionsResolver.Current = new ActionsResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolveActions());
|
||||
|
||||
//the database migration objects
|
||||
MigrationResolver.Current = new MigrationResolver(
|
||||
() => PluginManager.Current.ResolveTypes<IMigration>());
|
||||
ProfilingLogger.Logger,
|
||||
() => PluginManager.ResolveTypes<IMigration>());
|
||||
|
||||
// todo: remove once we drop IPropertyEditorValueConverter support.
|
||||
PropertyEditorValueConvertersResolver.Current = new PropertyEditorValueConvertersResolver(
|
||||
PluginManager.Current.ResolvePropertyEditorValueConverters());
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
PluginManager.ResolvePropertyEditorValueConverters());
|
||||
|
||||
// need to filter out the ones we dont want!!
|
||||
PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(
|
||||
PluginManager.Current.ResolveTypes<IPropertyValueConverter>());
|
||||
// need to filter out the ones we dont want!!
|
||||
PropertyValueConvertersResolver.Current = new PropertyValueConvertersResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
PluginManager.ResolveTypes<IPropertyValueConverter>());
|
||||
|
||||
// use the new DefaultShortStringHelper
|
||||
ShortStringHelperResolver.Current = new ShortStringHelperResolver(
|
||||
//new LegacyShortStringHelper());
|
||||
new DefaultShortStringHelper().WithDefaultConfig());
|
||||
new DefaultShortStringHelper(UmbracoConfig.For.UmbracoSettings()).WithDefaultConfig());
|
||||
|
||||
UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(
|
||||
typeof (DefaultUrlSegmentProvider));
|
||||
UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(
|
||||
ServiceProvider, ProfilingLogger.Logger,
|
||||
typeof(DefaultUrlSegmentProvider));
|
||||
|
||||
// by default, no factory is activated
|
||||
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver();
|
||||
}
|
||||
}
|
||||
PublishedContentModelFactoryResolver.Current = new PublishedContentModelFactoryResolver();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
using umbraco.interfaces;
|
||||
|
||||
@@ -11,12 +12,14 @@ namespace Umbraco.Core
|
||||
[Obsolete("IDataType is obsolete and is no longer used, it will be removed from the codebase in future versions")]
|
||||
internal sealed class DataTypesResolver : LegacyTransientObjectsResolver<DataTypesResolver, IDataType>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="dataTypes"></param>
|
||||
internal DataTypesResolver(Func<IEnumerable<Type>> dataTypes)
|
||||
: base(dataTypes)
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="dataTypes"></param>
|
||||
internal DataTypesResolver(IServiceProvider serviceProvider, ILogger logger, Func<IEnumerable<Type>> dataTypes)
|
||||
: base(serviceProvider, logger, dataTypes)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Configuration;
|
||||
using System.Xml.Linq;
|
||||
using Semver;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -13,6 +14,7 @@ using Umbraco.Core.Persistence;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
using Umbraco.Core.Persistence.Migrations.Initial;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
@@ -25,19 +27,61 @@ namespace Umbraco.Core
|
||||
public class DatabaseContext
|
||||
{
|
||||
private readonly IDatabaseFactory _factory;
|
||||
private readonly ILogger _logger;
|
||||
private readonly SqlSyntaxProviders _syntaxProviders;
|
||||
private bool _configured;
|
||||
private bool _canConnect;
|
||||
private volatile bool _connectCheck = false;
|
||||
private readonly object _locker = new object();
|
||||
private string _connectionString;
|
||||
private string _providerName;
|
||||
private DatabaseSchemaResult _result;
|
||||
|
||||
[Obsolete("Use the constructor specifying all dependencies instead")]
|
||||
public DatabaseContext(IDatabaseFactory factory)
|
||||
: this(factory, LoggerResolver.Current.Logger, new SqlSyntaxProviders(new ISqlSyntaxProvider[]
|
||||
{
|
||||
new MySqlSyntaxProvider(LoggerResolver.Current.Logger),
|
||||
new SqlCeSyntaxProvider(),
|
||||
new SqlServerSyntaxProvider()
|
||||
}))
|
||||
{
|
||||
_factory = factory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="syntaxProviders"></param>
|
||||
public DatabaseContext(IDatabaseFactory factory, ILogger logger, SqlSyntaxProviders syntaxProviders)
|
||||
{
|
||||
if (factory == null) throw new ArgumentNullException("factory");
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
if (syntaxProviders == null) throw new ArgumentNullException("syntaxProviders");
|
||||
|
||||
_factory = factory;
|
||||
_logger = logger;
|
||||
_syntaxProviders = syntaxProviders;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a configured DatabaseContext
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
/// <param name="logger"></param>
|
||||
/// <param name="sqlSyntax"></param>
|
||||
/// <param name="providerName"></param>
|
||||
public DatabaseContext(IDatabaseFactory factory, ILogger logger, ISqlSyntaxProvider sqlSyntax, string providerName)
|
||||
{
|
||||
_providerName = providerName;
|
||||
SqlSyntax = sqlSyntax;
|
||||
SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax;
|
||||
_factory = factory;
|
||||
_logger = logger;
|
||||
_configured = true;
|
||||
}
|
||||
|
||||
public ISqlSyntaxProvider SqlSyntax { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Database"/> object for doing CRUD operations
|
||||
/// against custom tables that resides in the Umbraco database.
|
||||
@@ -46,7 +90,7 @@ namespace Umbraco.Core
|
||||
/// This should not be used for CRUD operations or queries against the
|
||||
/// standard Umbraco tables! Use the Public services for that.
|
||||
/// </remarks>
|
||||
public UmbracoDatabase Database
|
||||
public virtual UmbracoDatabase Database
|
||||
{
|
||||
get { return _factory.CreateDatabase(); }
|
||||
}
|
||||
@@ -54,7 +98,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Boolean indicating whether the database has been configured
|
||||
/// </summary>
|
||||
public bool IsDatabaseConfigured
|
||||
public virtual bool IsDatabaseConfigured
|
||||
{
|
||||
get { return _configured; }
|
||||
}
|
||||
@@ -62,33 +106,21 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Determines if the db can be connected to
|
||||
/// </summary>
|
||||
public bool CanConnect
|
||||
public virtual bool CanConnect
|
||||
{
|
||||
get
|
||||
{
|
||||
if (IsDatabaseConfigured == false) return false;
|
||||
|
||||
//double check lock so that it is only checked once and is fast
|
||||
if (_connectCheck == false)
|
||||
{
|
||||
lock (_locker)
|
||||
{
|
||||
if (_canConnect == false)
|
||||
{
|
||||
_canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
|
||||
_connectCheck = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _canConnect;
|
||||
var canConnect = DbConnectionExtensions.IsConnectionAvailable(ConnectionString, DatabaseProvider);
|
||||
LogHelper.Info<DatabaseContext>("CanConnect = " + canConnect);
|
||||
return canConnect;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configured umbraco db connection string.
|
||||
/// </summary>
|
||||
public string ConnectionString
|
||||
public virtual string ConnectionString
|
||||
{
|
||||
get { return _connectionString; }
|
||||
}
|
||||
@@ -106,7 +138,7 @@ namespace Umbraco.Core
|
||||
_providerName = "System.Data.SqlClient";
|
||||
if (ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName] != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName))
|
||||
if (string.IsNullOrEmpty(ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName) == false)
|
||||
_providerName = ConfigurationManager.ConnectionStrings[GlobalSettings.UmbracoConnectionName].ProviderName;
|
||||
}
|
||||
else
|
||||
@@ -120,7 +152,7 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Returns the Type of DatabaseProvider used
|
||||
/// </summary>
|
||||
public DatabaseProviders DatabaseProvider
|
||||
public virtual DatabaseProviders DatabaseProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -324,7 +356,7 @@ namespace Umbraco.Core
|
||||
|
||||
xml.Save(fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
LogHelper.Info<DatabaseContext>("Configured a new ConnectionString using the '" + providerName + "' provider.");
|
||||
_logger.Info<DatabaseContext>("Configured a new ConnectionString using the '" + providerName + "' provider.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -398,12 +430,23 @@ namespace Umbraco.Core
|
||||
|
||||
internal void Initialize(string providerName)
|
||||
{
|
||||
//only configure once!
|
||||
if (_configured == true) return;
|
||||
|
||||
_providerName = providerName;
|
||||
|
||||
try
|
||||
{
|
||||
SqlSyntaxContext.SqlSyntaxProvider =
|
||||
SqlSyntaxProvidersResolver.Current.GetByProviderNameOrDefault(providerName);
|
||||
if (_syntaxProviders != null)
|
||||
{
|
||||
SqlSyntax = _syntaxProviders.GetByProviderNameOrDefault(providerName);
|
||||
}
|
||||
else if (SqlSyntax == null)
|
||||
{
|
||||
throw new InvalidOperationException("No " + typeof(ISqlSyntaxProvider) + " specified or no " + typeof(SqlSyntaxProviders) + " instance specified");
|
||||
}
|
||||
|
||||
SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax;
|
||||
|
||||
_configured = true;
|
||||
}
|
||||
@@ -411,8 +454,8 @@ namespace Umbraco.Core
|
||||
{
|
||||
_configured = false;
|
||||
|
||||
LogHelper.Info<DatabaseContext>("Initialization of the DatabaseContext failed with following error: " + e.Message);
|
||||
LogHelper.Info<DatabaseContext>(e.StackTrace);
|
||||
_logger.Info<DatabaseContext>("Initialization of the DatabaseContext failed with following error: " + e.Message);
|
||||
_logger.Info<DatabaseContext>(e.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,8 +470,8 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
private void DetermineSqlServerVersion()
|
||||
{
|
||||
|
||||
var sqlServerSyntax = SqlSyntaxContext.SqlSyntaxProvider as SqlServerSyntaxProvider;
|
||||
|
||||
var sqlServerSyntax = SqlSyntax as SqlServerSyntaxProvider;
|
||||
if (sqlServerSyntax != null)
|
||||
{
|
||||
//this will not execute now, it is lazy so will only execute when we need to actually know
|
||||
@@ -479,14 +522,14 @@ namespace Umbraco.Core
|
||||
throw new InvalidOperationException("Cannot use MySql in Medium Trust configuration");
|
||||
}
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
var dbSchema = new DatabaseSchemaCreation(database);
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName, _logger);
|
||||
var dbSchema = new DatabaseSchemaCreation(database, _logger, SqlSyntax);
|
||||
_result = dbSchema.ValidateSchema();
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
internal Result CreateDatabaseSchemaAndData()
|
||||
internal Result CreateDatabaseSchemaAndData(ApplicationContext applicationContext)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -496,17 +539,17 @@ namespace Umbraco.Core
|
||||
return readyForInstall.Result;
|
||||
}
|
||||
|
||||
LogHelper.Info<DatabaseContext>("Database configuration status: Started");
|
||||
_logger.Info<DatabaseContext>("Database configuration status: Started");
|
||||
|
||||
string message;
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName, _logger);
|
||||
|
||||
// If MySQL, we're going to ensure that database calls are maintaining proper casing as to remove the necessity for checks
|
||||
// for case insensitive queries. In an ideal situation (which is what we're striving for), all calls would be case sensitive.
|
||||
|
||||
/*
|
||||
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database);
|
||||
if (supportsCaseInsensitiveQueries == false)
|
||||
{
|
||||
message = "<p> </p><p>The database you're trying to use does not support case insensitive queries. <br />We currently do not support these types of databases.</p>" +
|
||||
@@ -523,21 +566,24 @@ namespace Umbraco.Core
|
||||
message = GetResultMessageForMySql();
|
||||
|
||||
var schemaResult = ValidateDatabaseSchema();
|
||||
var installedVersion = schemaResult.DetermineInstalledVersion();
|
||||
|
||||
var installedSchemaVersion = schemaResult.DetermineInstalledVersion();
|
||||
|
||||
//If Configuration Status is empty and the determined version is "empty" its a new install - otherwise upgrade the existing
|
||||
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedVersion.Equals(new Version(0, 0, 0)))
|
||||
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedSchemaVersion.Equals(new Version(0, 0, 0)))
|
||||
{
|
||||
database.CreateDatabaseSchema();
|
||||
var helper = new DatabaseSchemaHelper(database, _logger, SqlSyntax);
|
||||
helper.CreateDatabaseSchema(true, applicationContext);
|
||||
|
||||
message = message + "<p>Installation completed!</p>";
|
||||
|
||||
//now that everything is done, we need to determine the version of SQL server that is executing
|
||||
LogHelper.Info<DatabaseContext>("Database configuration status: " + message);
|
||||
_logger.Info<DatabaseContext>("Database configuration status: " + message);
|
||||
return new Result { Message = message, Success = true, Percentage = "100" };
|
||||
}
|
||||
|
||||
//we need to do an upgrade so return a new status message and it will need to be done during the next step
|
||||
LogHelper.Info<DatabaseContext>("Database requires upgrade");
|
||||
_logger.Info<DatabaseContext>("Database requires upgrade");
|
||||
message = "<p>Upgrading database, this may take some time...</p>";
|
||||
return new Result
|
||||
{
|
||||
@@ -557,7 +603,7 @@ namespace Umbraco.Core
|
||||
/// This assumes all of the previous checks are done!
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal Result UpgradeSchemaAndData()
|
||||
internal Result UpgradeSchemaAndData(IMigrationEntryService migrationEntryService)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -568,29 +614,69 @@ namespace Umbraco.Core
|
||||
return readyForInstall.Result;
|
||||
}
|
||||
|
||||
LogHelper.Info<DatabaseContext>("Database upgrade started");
|
||||
_logger.Info<DatabaseContext>("Database upgrade started");
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
//var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName, _logger);
|
||||
//var supportsCaseInsensitiveQueries = SqlSyntax.SupportsCaseInsensitiveQueries(database);
|
||||
|
||||
var message = GetResultMessageForMySql();
|
||||
|
||||
var schemaResult = ValidateDatabaseSchema();
|
||||
var installedVersion = schemaResult.DetermineInstalledVersion();
|
||||
|
||||
var installedSchemaVersion = new SemVersion(schemaResult.DetermineInstalledVersion());
|
||||
|
||||
var installedMigrationVersion = new SemVersion(0);
|
||||
//we cannot check the migrations table if it doesn't exist, this will occur when upgrading to 7.3
|
||||
if (schemaResult.ValidTables.Any(x => x.InvariantEquals("umbracoMigration")))
|
||||
{
|
||||
installedMigrationVersion = schemaResult.DetermineInstalledVersionByMigrations(migrationEntryService);
|
||||
}
|
||||
|
||||
var targetVersion = UmbracoVersion.Current;
|
||||
|
||||
//In some cases - like upgrading from 7.2.6 -> 7.3, there will be no migration information in the database and therefore it will
|
||||
// return a version of 0.0.0 and we don't necessarily want to run all migrations from 0 -> 7.3, so we'll just ensure that the
|
||||
// migrations are run for the target version
|
||||
if (installedMigrationVersion == new SemVersion(new Version(0, 0, 0)) && installedSchemaVersion > new SemVersion(new Version(0, 0, 0)))
|
||||
{
|
||||
//set the installedMigrationVersion to be one less than the target so the latest migrations are guaranteed to execute
|
||||
installedMigrationVersion = new SemVersion(targetVersion.SubtractRevision());
|
||||
}
|
||||
|
||||
//Figure out what our current installed version is. If the web.config doesn't have a version listed, then we'll use the minimum
|
||||
// version detected between the schema installed and the migrations listed in the migration table.
|
||||
// If there is a version in the web.config, we'll take the minimum between the listed migration in the db and what
|
||||
// is declared in the web.config.
|
||||
|
||||
var currentInstalledVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
|
||||
//Take the minimum version between the detected schema version and the installed migration version
|
||||
? new[] {installedSchemaVersion, installedMigrationVersion}.Min()
|
||||
//Take the minimum version between the installed migration version and the version specified in the config
|
||||
: new[] { SemVersion.Parse(GlobalSettings.ConfigurationStatus), installedMigrationVersion }.Min();
|
||||
|
||||
//Ok, another edge case here. If the current version is a pre-release,
|
||||
// then we want to ensure all migrations for the current release are executed.
|
||||
if (currentInstalledVersion.Prerelease.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
currentInstalledVersion = new SemVersion(currentInstalledVersion.GetVersion().SubtractRevision());
|
||||
}
|
||||
|
||||
//DO the upgrade!
|
||||
|
||||
var currentVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
|
||||
? installedVersion
|
||||
: new Version(GlobalSettings.ConfigurationStatus);
|
||||
var targetVersion = UmbracoVersion.Current;
|
||||
var runner = new MigrationRunner(currentVersion, targetVersion, GlobalSettings.UmbracoMigrationName);
|
||||
var runner = new MigrationRunner(migrationEntryService, _logger, currentInstalledVersion, UmbracoVersion.GetSemanticVersion(), GlobalSettings.UmbracoMigrationName);
|
||||
|
||||
var upgraded = runner.Execute(database, true);
|
||||
|
||||
if (upgraded == false)
|
||||
{
|
||||
throw new ApplicationException("Upgrading failed, either an error occurred during the upgrade process or an event canceled the upgrade process, see log for full details");
|
||||
}
|
||||
|
||||
message = message + "<p>Upgrade completed!</p>";
|
||||
|
||||
//now that everything is done, we need to determine the version of SQL server that is executing
|
||||
|
||||
LogHelper.Info<DatabaseContext>("Database configuration status: " + message);
|
||||
_logger.Info<DatabaseContext>("Database configuration status: " + message);
|
||||
|
||||
return new Result { Message = message, Success = true, Percentage = "100" };
|
||||
}
|
||||
@@ -602,7 +688,7 @@ namespace Umbraco.Core
|
||||
|
||||
private string GetResultMessageForMySql()
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
|
||||
if (SqlSyntax.GetType() == typeof(MySqlSyntaxProvider))
|
||||
{
|
||||
return "<p> </p><p>Congratulations, the database step ran successfully!</p>" +
|
||||
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
|
||||
@@ -628,7 +714,7 @@ namespace Umbraco.Core
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
|
||||
if (SqlSyntax.GetType() == typeof(MySqlSyntaxProvider))
|
||||
{
|
||||
return "<p> </p><p>Congratulations, the database step ran successfully!</p>" +
|
||||
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
|
||||
@@ -665,11 +751,11 @@ namespace Umbraco.Core
|
||||
|
||||
private Result HandleInstallException(Exception ex)
|
||||
{
|
||||
LogHelper.Error<DatabaseContext>("Database configuration failed", ex);
|
||||
_logger.Error<DatabaseContext>("Database configuration failed", ex);
|
||||
|
||||
if (_result != null)
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("The database schema validation produced the following summary: \n" + _result.GetSummary());
|
||||
_logger.Info<DatabaseContext>("The database schema validation produced the following summary: \n" + _result.GetSummary());
|
||||
}
|
||||
|
||||
return new Result
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static class DelegateExtensions
|
||||
{
|
||||
public static Attempt<T> RetryUntilSuccessOrTimeout<T>(this Func<Attempt<T>> task, TimeSpan timeout, TimeSpan pause)
|
||||
{
|
||||
if (pause.TotalMilliseconds < 0)
|
||||
{
|
||||
throw new ArgumentException("pause must be >= 0 milliseconds");
|
||||
}
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
do
|
||||
{
|
||||
var result = task();
|
||||
if (result) { return result; }
|
||||
Thread.Sleep((int)pause.TotalMilliseconds);
|
||||
}
|
||||
while (stopwatch.Elapsed < timeout);
|
||||
return Attempt<T>.Fail();
|
||||
}
|
||||
|
||||
public static Attempt<T> RetryUntilSuccessOrMaxAttempts<T>(this Func<int, Attempt<T>> task, int totalAttempts, TimeSpan pause)
|
||||
{
|
||||
if (pause.TotalMilliseconds < 0)
|
||||
{
|
||||
throw new ArgumentException("pause must be >= 0 milliseconds");
|
||||
}
|
||||
int attempts = 0;
|
||||
do
|
||||
{
|
||||
attempts++;
|
||||
var result = task(attempts);
|
||||
if (result) { return result; }
|
||||
Thread.Sleep((int)pause.TotalMilliseconds);
|
||||
}
|
||||
while (attempts < totalAttempts);
|
||||
return Attempt<T>.Fail();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
|
||||
namespace Umbraco.Core.Dictionary
|
||||
@@ -12,15 +14,22 @@ namespace Umbraco.Core.Dictionary
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used by developers at runtime to set their ICultureDictionaryFactory at app startup
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
[Obsolete("Use SetDictionaryFactory instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void SetContentStore(ICultureDictionaryFactory factory)
|
||||
{
|
||||
Value = factory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Can be used by developers at runtime to set their ICultureDictionaryFactory at app startup
|
||||
/// </summary>
|
||||
/// <param name="factory"></param>
|
||||
public void SetDictionaryFactory(ICultureDictionaryFactory factory)
|
||||
{
|
||||
Value = factory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the ICultureDictionaryFactory
|
||||
/// </summary>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Umbraco.Core.Dictionary
|
||||
@@ -19,5 +20,12 @@ namespace Umbraco.Core.Dictionary
|
||||
/// Returns the current culture
|
||||
/// </summary>
|
||||
CultureInfo Culture { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the child dictionary entries for a given key
|
||||
/// </summary>
|
||||
/// <param name="key"></param>
|
||||
/// <returns></returns>
|
||||
IDictionary<string, string> GetChildren(string key);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web.Mvc;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core
|
||||
@@ -135,20 +134,6 @@ namespace Umbraco.Core
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a dictionary to a FormCollection
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
public static FormCollection ToFormCollection(this IDictionary<string, object> d)
|
||||
{
|
||||
var n = new FormCollection();
|
||||
foreach (var i in d)
|
||||
{
|
||||
n.Add(i.Key, Convert.ToString(i.Value));
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Merges all key/values from the sources dictionaries into the destination dictionary
|
||||
|
||||
@@ -4,69 +4,58 @@ using System.Threading;
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Abstract implementation of logic commonly required to safely handle disposable unmanaged resources.
|
||||
/// Abstract implementation of IDisposable.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Can also be used as a pattern for when inheriting is not possible.
|
||||
///
|
||||
/// See also: https://msdn.microsoft.com/en-us/library/b1yfkh5e%28v=vs.110%29.aspx
|
||||
/// See also: https://lostechies.com/chrispatterson/2012/11/29/idisposable-done-right/
|
||||
///
|
||||
/// Note: if an object's ctor throws, it will never be disposed, and so if that ctor
|
||||
/// has allocated disposable objects, it should take care of disposing them.
|
||||
/// </remarks>
|
||||
public abstract class DisposableObject : IDisposable
|
||||
{
|
||||
private bool _disposed;
|
||||
private readonly ReaderWriterLockSlim _disposalLocker = new ReaderWriterLockSlim();
|
||||
private readonly object _locko = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is disposed.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this instance is disposed; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
public bool IsDisposed
|
||||
{
|
||||
get { return _disposed; }
|
||||
}
|
||||
// gets a value indicating whether this instance is disposed.
|
||||
// for internal tests only (not thread safe)
|
||||
//TODO make this internal + rename "Disposed" when we can break compatibility
|
||||
public bool IsDisposed { get { return _disposed; } }
|
||||
|
||||
/// <summary>
|
||||
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
|
||||
/// </summary>
|
||||
/// <filterpriority>2</filterpriority>
|
||||
// implements IDisposable
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
|
||||
// Use SupressFinalize in case a subclass of this type implements a finalizer.
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
// finalizer
|
||||
~DisposableObject()
|
||||
{
|
||||
// Run dispose but let the class know it was due to the finalizer running.
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
//TODO make this private, non-virtual when we can break compatibility
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
// Only operate if we haven't already disposed
|
||||
if (IsDisposed || !disposing) return;
|
||||
lock (_locko)
|
||||
{
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
using (new WriteLock(_disposalLocker))
|
||||
{
|
||||
// Check again now we're inside the lock
|
||||
if (IsDisposed) return;
|
||||
DisposeUnmanagedResources();
|
||||
|
||||
// Call to actually release resources. This method is only
|
||||
// kept separate so that the entire disposal logic can be used as a VS snippet
|
||||
DisposeResources();
|
||||
|
||||
// Indicate that the instance has been disposed.
|
||||
_disposed = true;
|
||||
}
|
||||
if (disposing)
|
||||
DisposeResources();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the disposal of resources. Derived from abstract class <see cref="DisposableObject"/> which handles common required locking logic.
|
||||
/// </summary>
|
||||
protected abstract void DisposeResources();
|
||||
|
||||
protected virtual void DisposeUnmanagedResources()
|
||||
{
|
||||
|
||||
}
|
||||
{ }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -9,32 +10,65 @@ namespace Umbraco.Core
|
||||
/// <summary>
|
||||
/// Starts the timer and invokes a callback upon disposal. Provides a simple way of timing an operation by wrapping it in a <code>using</code> (C#) statement.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code>
|
||||
///
|
||||
/// using (DisposableTimer.TraceDuration{MyType}("starting", "finished"))
|
||||
/// {
|
||||
/// Thread.Sleep(567);
|
||||
/// }
|
||||
///
|
||||
/// Console.WriteLine("Testing Stopwatchdisposable, should be 567:");
|
||||
/// using (var timer = new DisposableTimer(result => Console.WriteLine("Took {0}ms", result)))
|
||||
/// {
|
||||
/// Thread.Sleep(567);
|
||||
/// }
|
||||
/// </code>
|
||||
/// </example>
|
||||
public class DisposableTimer : DisposableObject
|
||||
{
|
||||
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
|
||||
private readonly Stopwatch _stopwatch = Stopwatch.StartNew();
|
||||
private readonly Action<long> _callback;
|
||||
|
||||
protected DisposableTimer(Action<long> callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
internal enum LogType
|
||||
{
|
||||
Debug, Info
|
||||
}
|
||||
|
||||
public Stopwatch Stopwatch
|
||||
internal DisposableTimer(ILogger logger, LogType logType, IProfiler profiler, Type loggerType, string startMessage, string endMessage)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
if (loggerType == null) throw new ArgumentNullException("loggerType");
|
||||
|
||||
_callback = x =>
|
||||
{
|
||||
if (profiler != null)
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
}
|
||||
switch (logType)
|
||||
{
|
||||
case LogType.Debug:
|
||||
logger.Debug(loggerType, () => endMessage + " (took " + x + "ms)");
|
||||
break;
|
||||
case LogType.Info:
|
||||
logger.Info(loggerType, () => endMessage + " (took " + x + "ms)");
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("logType");
|
||||
}
|
||||
|
||||
};
|
||||
switch (logType)
|
||||
{
|
||||
case LogType.Debug:
|
||||
logger.Debug(loggerType, startMessage);
|
||||
break;
|
||||
case LogType.Info:
|
||||
logger.Info(loggerType, startMessage);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("logType");
|
||||
}
|
||||
|
||||
if (profiler != null)
|
||||
{
|
||||
profiler.Step(loggerType, startMessage);
|
||||
}
|
||||
}
|
||||
|
||||
protected internal DisposableTimer(Action<long> callback)
|
||||
{
|
||||
if (callback == null) throw new ArgumentNullException("callback");
|
||||
_callback = callback;
|
||||
}
|
||||
|
||||
public Stopwatch Stopwatch
|
||||
{
|
||||
get { return _stopwatch; }
|
||||
}
|
||||
@@ -51,25 +85,25 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
#region TraceDuration
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the other methods that specify strings instead of Func")]
|
||||
public static DisposableTimer TraceDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the other methods that specify strings instead of Func")]
|
||||
public static DisposableTimer TraceDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
var startMsg = startMessage();
|
||||
LogHelper.Info(loggerType, startMsg);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMsg);
|
||||
var profiler = ActivateProfiler(loggerType, startMsg);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Info(loggerType, () => completeMessage() + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMsg);
|
||||
});
|
||||
return new DisposableTimer(
|
||||
LoggerResolver.Current.Logger,
|
||||
LogType.Info,
|
||||
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
||||
loggerType,
|
||||
startMessage(),
|
||||
completeMessage());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -79,11 +113,19 @@ namespace Umbraco.Core
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Info and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
||||
public static DisposableTimer TraceDuration<T>(string startMessage)
|
||||
{
|
||||
return TraceDuration(typeof(T), startMessage, "Complete");
|
||||
@@ -96,20 +138,18 @@ namespace Umbraco.Core
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
||||
public static DisposableTimer TraceDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Info(loggerType, startMessage);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMessage);
|
||||
var profiler = ActivateProfiler(loggerType, startMessage);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Info(loggerType, () => completeMessage + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMessage);
|
||||
});
|
||||
}
|
||||
return new DisposableTimer(
|
||||
LoggerResolver.Current.Logger,
|
||||
LogType.Info,
|
||||
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
||||
loggerType,
|
||||
startMessage,
|
||||
completeMessage);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DebugDuration
|
||||
@@ -120,23 +160,26 @@ namespace Umbraco.Core
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage, string completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
}
|
||||
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, "Complete");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
||||
public static DisposableTimer DebugDuration<T>(string startMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, "Complete");
|
||||
}
|
||||
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the other methods that specify strings instead of Func")]
|
||||
public static DisposableTimer DebugDuration<T>(Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
return DebugDuration(typeof(T), startMessage, completeMessage);
|
||||
@@ -149,42 +192,29 @@ namespace Umbraco.Core
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Use the Umbraco.Core.Logging.ProfilingLogger to create instances of DisposableTimer")]
|
||||
public static DisposableTimer DebugDuration(Type loggerType, string startMessage, string completeMessage)
|
||||
{
|
||||
LogHelper.Debug(loggerType, startMessage);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMessage);
|
||||
var profiler = ActivateProfiler(loggerType, startMessage);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Debug(loggerType, () => completeMessage + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMessage);
|
||||
});
|
||||
return new DisposableTimer(
|
||||
LoggerResolver.Current.Logger,
|
||||
LogType.Debug,
|
||||
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
||||
loggerType,
|
||||
startMessage,
|
||||
completeMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a start and end log entry as Debug and tracks how long it takes until disposed.
|
||||
/// </summary>
|
||||
/// <param name="loggerType"></param>
|
||||
/// <param name="startMessage"></param>
|
||||
/// <param name="completeMessage"></param>
|
||||
/// <returns></returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use the other methods that specify strings instead of Func")]
|
||||
public static DisposableTimer DebugDuration(Type loggerType, Func<string> startMessage, Func<string> completeMessage)
|
||||
{
|
||||
var msg = startMessage();
|
||||
LogHelper.Debug(loggerType, msg);
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("Start: " + startMessage);
|
||||
var profiler = ActivateProfiler(loggerType, msg);
|
||||
return new DisposableTimer(x =>
|
||||
{
|
||||
profiler.DisposeIfDisposable();
|
||||
LogHelper.Debug(loggerType, () => completeMessage() + " (took " + x + "ms)");
|
||||
if (HttpContext.Current != null)
|
||||
HttpContext.Current.Trace.Write("End: " + startMessage);
|
||||
});
|
||||
return new DisposableTimer(
|
||||
LoggerResolver.Current.Logger,
|
||||
LogType.Debug,
|
||||
ProfilerResolver.HasCurrent ? ProfilerResolver.Current.Profiler : null,
|
||||
loggerType,
|
||||
startMessage(),
|
||||
completeMessage());
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -196,18 +226,5 @@ namespace Umbraco.Core
|
||||
_callback.Invoke(Stopwatch.ElapsedMilliseconds);
|
||||
}
|
||||
|
||||
private static IDisposable ActivateProfiler(Type loggerType, string profileName)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ProfilerResolver.Current.Profiler.Step(loggerType, profileName);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
//swallow this exception, it will occur if the ProfilerResolver is not initialized... generally only in
|
||||
// unit tests.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,7 @@ namespace Umbraco.Core
|
||||
/// <param name="f">The select child.</param>
|
||||
/// <typeparam name="T">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[Obsolete("Do not use, use SelectRecursive instead which has far less potential of re-iterating an iterator which may cause significantly more SQL queries")]
|
||||
public static IEnumerable<T> FlattenList<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> f)
|
||||
{
|
||||
return e.SelectMany(c => f(c).FlattenList(f)).Concat(e);
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Security.Permissions;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Event args for that can support cancellation
|
||||
/// </summary>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
@@ -11,15 +11,30 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
private bool _cancel;
|
||||
|
||||
public CancellableEventArgs(bool canCancel)
|
||||
public CancellableEventArgs(bool canCancel, EventMessages eventMessages)
|
||||
{
|
||||
if (eventMessages == null) throw new ArgumentNullException("eventMessages");
|
||||
CanCancel = canCancel;
|
||||
Messages = eventMessages;
|
||||
}
|
||||
|
||||
public CancellableEventArgs(bool canCancel)
|
||||
{
|
||||
CanCancel = canCancel;
|
||||
}
|
||||
//create a standalone messages
|
||||
Messages = new EventMessages();
|
||||
}
|
||||
|
||||
public CancellableEventArgs()
|
||||
public CancellableEventArgs(EventMessages eventMessages)
|
||||
: this(true, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableEventArgs()
|
||||
: this(true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Flag to determine if this instance will support being cancellable
|
||||
/// </summary>
|
||||
@@ -32,7 +47,7 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!CanCancel)
|
||||
if (CanCancel == false)
|
||||
{
|
||||
throw new InvalidOperationException("This event argument class does not support cancelling.");
|
||||
}
|
||||
@@ -40,12 +55,28 @@ namespace Umbraco.Core.Events
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!CanCancel)
|
||||
if (CanCancel == false)
|
||||
{
|
||||
throw new InvalidOperationException("This event argument class does not support cancelling.");
|
||||
}
|
||||
_cancel = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// if this instance supports cancellation, this will set Cancel to true with an affiliated cancellation message
|
||||
/// </summary>
|
||||
/// <param name="cancelationMessage"></param>
|
||||
public void CancelOperation(EventMessage cancelationMessage)
|
||||
{
|
||||
Cancel = true;
|
||||
cancelationMessage.IsDefaultEventMessage = true;
|
||||
Messages.Add(cancelationMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the EventMessages object which is used to add messages to the message collection for this event
|
||||
/// </summary>
|
||||
public EventMessages Messages { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,18 @@ namespace Umbraco.Core.Events
|
||||
public class CancellableObjectEventArgs<T> : CancellableEventArgs
|
||||
{
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel)
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(canCancel, eventMessages)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
|
||||
: this(eventObject, true, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel)
|
||||
: base(canCancel)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
|
||||
@@ -4,12 +4,56 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
public class DeleteEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the delete operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
public DeleteEventArgs(IEnumerable<TEntity> eventObject, bool canCancel) : base(eventObject, canCancel)
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the delete operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public DeleteEventArgs(IEnumerable<TEntity> eventObject, bool canCancel, EventMessages eventMessages) : base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
MediaFilesToDelete = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the delete operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public DeleteEventArgs(IEnumerable<TEntity> eventObject, EventMessages eventMessages) : base(eventObject, eventMessages)
|
||||
{
|
||||
MediaFilesToDelete = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public DeleteEventArgs(TEntity eventObject, EventMessages eventMessages)
|
||||
: base(new List<TEntity> { eventObject }, eventMessages)
|
||||
{
|
||||
MediaFilesToDelete = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public DeleteEventArgs(TEntity eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(new List<TEntity> { eventObject }, canCancel, eventMessages)
|
||||
{
|
||||
MediaFilesToDelete = new List<string>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the delete operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
public DeleteEventArgs(IEnumerable<TEntity> eventObject, bool canCancel) : base(eventObject, canCancel)
|
||||
{
|
||||
MediaFilesToDelete = new List<string>();
|
||||
}
|
||||
@@ -60,7 +104,13 @@ namespace Umbraco.Core.Events
|
||||
|
||||
public class DeleteEventArgs : CancellableEventArgs
|
||||
{
|
||||
public DeleteEventArgs(int id, bool canCancel)
|
||||
public DeleteEventArgs(int id, bool canCancel, EventMessages eventMessages)
|
||||
: base(canCancel, eventMessages)
|
||||
{
|
||||
Id = id;
|
||||
}
|
||||
|
||||
public DeleteEventArgs(int id, bool canCancel)
|
||||
: base(canCancel)
|
||||
{
|
||||
Id = id;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
@@ -7,16 +8,16 @@ namespace Umbraco.Core.Events
|
||||
/// </summary>
|
||||
public static class EventExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Raises the event and returns a boolean value indicating if the event was cancelled
|
||||
/// </summary>
|
||||
/// <typeparam name="TSender"></typeparam>
|
||||
/// <typeparam name="TArgs"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsRaisedEventCancelled<TSender, TArgs>(
|
||||
/// <summary>
|
||||
/// Raises the event and returns a boolean value indicating if the event was cancelled
|
||||
/// </summary>
|
||||
/// <typeparam name="TSender"></typeparam>
|
||||
/// <typeparam name="TArgs"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="sender"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsRaisedEventCancelled<TSender, TArgs>(
|
||||
this TypedEventHandler<TSender, TArgs> eventHandler,
|
||||
TArgs args,
|
||||
TSender sender)
|
||||
@@ -27,16 +28,16 @@ namespace Umbraco.Core.Events
|
||||
|
||||
return args.Cancel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the event
|
||||
/// </summary>
|
||||
/// <typeparam name="TSender"></typeparam>
|
||||
/// <typeparam name="TArgs"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="sender"></param>
|
||||
public static void RaiseEvent<TSender, TArgs>(
|
||||
|
||||
/// <summary>
|
||||
/// Raises the event
|
||||
/// </summary>
|
||||
/// <typeparam name="TSender"></typeparam>
|
||||
/// <typeparam name="TArgs"></typeparam>
|
||||
/// <param name="eventHandler"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <param name="sender"></param>
|
||||
public static void RaiseEvent<TSender, TArgs>(
|
||||
this TypedEventHandler<TSender, TArgs> eventHandler,
|
||||
TArgs args,
|
||||
TSender sender)
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// An event message
|
||||
/// </summary>
|
||||
public sealed class EventMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="EventMessage"/> class.
|
||||
/// </summary>
|
||||
public EventMessage(string category, string message, EventMessageType messageType = EventMessageType.Default)
|
||||
{
|
||||
Category = category;
|
||||
Message = message;
|
||||
MessageType = messageType;
|
||||
}
|
||||
|
||||
public string Category { get; private set; }
|
||||
public string Message { get; private set; }
|
||||
public EventMessageType MessageType { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// This is used to track if this message should be used as a default message so that Umbraco doesn't also append it's own default messages
|
||||
/// </summary>
|
||||
internal bool IsDefaultEventMessage { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event messages collection
|
||||
/// </summary>
|
||||
public sealed class EventMessages : DisposableObject
|
||||
{
|
||||
private readonly List<EventMessage> _msgs = new List<EventMessage>();
|
||||
|
||||
public void Add(EventMessage msg)
|
||||
{
|
||||
_msgs.Add(msg);
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
get { return _msgs.Count; }
|
||||
}
|
||||
|
||||
public IEnumerable<EventMessage> GetAll()
|
||||
{
|
||||
return _msgs;
|
||||
}
|
||||
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
_msgs.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event messages factory
|
||||
/// </summary>
|
||||
public interface IEventMessagesFactory
|
||||
{
|
||||
EventMessages Get();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// The type of event message
|
||||
/// </summary>
|
||||
public enum EventMessageType
|
||||
{
|
||||
Default = 0,
|
||||
Info = 1,
|
||||
Error = 2,
|
||||
Success = 3,
|
||||
Warning = 4
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using Semver;
|
||||
using Umbraco.Core.Persistence.Migrations;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
@@ -13,11 +15,20 @@ namespace Umbraco.Core.Events
|
||||
/// <param name="targetVersion"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
}
|
||||
|
||||
[Obsolete("Use constructor accepting UmbracoVersion instances instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, Version configuredVersion, Version targetVersion, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
ConfiguredVersion = configuredVersion;
|
||||
TargetVersion = targetVersion;
|
||||
ConfiguredSemVersion = new SemVersion(configuredVersion);
|
||||
TargetSemVersion = new SemVersion(targetVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -28,12 +39,12 @@ namespace Umbraco.Core.Events
|
||||
/// <param name="targetVersion"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
internal MigrationEventArgs(IList<IMigration> eventObject, MigrationContext migrationContext, Version configuredVersion, Version targetVersion, bool canCancel)
|
||||
internal MigrationEventArgs(IList<IMigration> eventObject, MigrationContext migrationContext, SemVersion configuredVersion, SemVersion targetVersion, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
MigrationContext = migrationContext;
|
||||
ConfiguredVersion = configuredVersion;
|
||||
TargetVersion = targetVersion;
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -42,11 +53,20 @@ namespace Umbraco.Core.Events
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="configuredVersion"></param>
|
||||
/// <param name="targetVersion"></param>
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, SemVersion configuredVersion, SemVersion targetVersion)
|
||||
: base(eventObject)
|
||||
{
|
||||
ConfiguredSemVersion = configuredVersion;
|
||||
TargetSemVersion = targetVersion;
|
||||
}
|
||||
|
||||
[Obsolete("Use constructor accepting UmbracoVersion instances instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public MigrationEventArgs(IList<IMigration> eventObject, Version configuredVersion, Version targetVersion)
|
||||
: base(eventObject)
|
||||
{
|
||||
ConfiguredVersion = configuredVersion;
|
||||
TargetVersion = targetVersion;
|
||||
ConfiguredSemVersion = new SemVersion(configuredVersion);
|
||||
TargetSemVersion = new SemVersion(targetVersion);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -57,9 +77,23 @@ namespace Umbraco.Core.Events
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
public Version ConfiguredVersion { get; private set; }
|
||||
[Obsolete("Use ConfiguredSemVersion instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Version ConfiguredVersion
|
||||
{
|
||||
get { return ConfiguredSemVersion.GetVersion(); }
|
||||
}
|
||||
|
||||
public Version TargetVersion { get; private set; }
|
||||
[Obsolete("Use TargetUmbracoVersion instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public Version TargetVersion
|
||||
{
|
||||
get { return TargetSemVersion.GetVersion(); }
|
||||
}
|
||||
|
||||
public SemVersion ConfiguredSemVersion { get; private set; }
|
||||
|
||||
public SemVersion TargetSemVersion { get; private set; }
|
||||
|
||||
internal MigrationContext MigrationContext { get; private set; }
|
||||
}
|
||||
|
||||
@@ -4,22 +4,51 @@ using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class MoveEventInfo<TEntity>
|
||||
{
|
||||
public MoveEventInfo(TEntity entity, string originalPath, int newParentId)
|
||||
{
|
||||
Entity = entity;
|
||||
OriginalPath = originalPath;
|
||||
NewParentId = newParentId;
|
||||
}
|
||||
|
||||
public TEntity Entity { get; set; }
|
||||
public string OriginalPath { get; set; }
|
||||
public int NewParentId { get; set; }
|
||||
}
|
||||
|
||||
public class MoveEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting a collection of MoveEventInfo objects
|
||||
/// </summary>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
/// <param name="moveInfo">
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(bool canCancel, EventMessages eventMessages, params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity), canCancel, eventMessages)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
throw new ArgumentException("moveInfo argument must contain at least one item");
|
||||
}
|
||||
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a collection of MoveEventInfo objects
|
||||
/// </summary>
|
||||
/// <param name="eventMessages"></param>
|
||||
/// <param name="moveInfo">
|
||||
/// A colleciton of MoveEventInfo objects that exposes all entities that have been moved during a single move operation
|
||||
/// </param>
|
||||
public MoveEventArgs(EventMessages eventMessages, params MoveEventInfo<TEntity>[] moveInfo)
|
||||
: base(default(TEntity), eventMessages)
|
||||
{
|
||||
if (moveInfo.FirstOrDefault() == null)
|
||||
{
|
||||
throw new ArgumentException("moveInfo argument must contain at least one item");
|
||||
}
|
||||
|
||||
MoveInfoCollection = moveInfo;
|
||||
//assign the legacy props
|
||||
EventObject = moveInfo.First().Entity;
|
||||
ParentId = moveInfo.First().NewParentId;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a collection of MoveEventInfo objects
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class MoveEventInfo<TEntity>
|
||||
{
|
||||
public MoveEventInfo(TEntity entity, string originalPath, int newParentId)
|
||||
{
|
||||
Entity = entity;
|
||||
OriginalPath = originalPath;
|
||||
NewParentId = newParentId;
|
||||
}
|
||||
|
||||
public TEntity Entity { get; set; }
|
||||
public string OriginalPath { get; set; }
|
||||
public int NewParentId { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,39 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
public class NewEventArgs<TEntity> : CancellableObjectEventArgs<TEntity>
|
||||
{
|
||||
public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, int parentId) : base(eventObject, canCancel)
|
||||
|
||||
|
||||
public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, int parentId, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
Alias = alias;
|
||||
ParentId = parentId;
|
||||
}
|
||||
|
||||
public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, TEntity parent, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
Alias = alias;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
public NewEventArgs(TEntity eventObject, string @alias, int parentId, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{
|
||||
Alias = alias;
|
||||
ParentId = parentId;
|
||||
}
|
||||
|
||||
public NewEventArgs(TEntity eventObject, string @alias, TEntity parent, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{
|
||||
Alias = alias;
|
||||
Parent = parent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public NewEventArgs(TEntity eventObject, bool canCancel, string @alias, int parentId) : base(eventObject, canCancel)
|
||||
{
|
||||
Alias = alias;
|
||||
ParentId = parentId;
|
||||
|
||||
@@ -4,6 +4,52 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
public class PublishEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the publish operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="isAllPublished"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public PublishEventArgs(IEnumerable<TEntity> eventObject, bool canCancel, bool isAllPublished, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
IsAllRepublished = isAllPublished;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the publish operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public PublishEventArgs(IEnumerable<TEntity> eventObject, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public PublishEventArgs(TEntity eventObject, EventMessages eventMessages)
|
||||
: base(new List<TEntity> { eventObject }, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="isAllPublished"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public PublishEventArgs(TEntity eventObject, bool canCancel, bool isAllPublished, EventMessages eventMessages)
|
||||
: base(new List<TEntity> { eventObject }, canCancel, eventMessages)
|
||||
{
|
||||
IsAllRepublished = isAllPublished;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the publish operation
|
||||
/// </summary>
|
||||
|
||||
@@ -4,12 +4,55 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
public class SaveEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the saving operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
public SaveEventArgs(IEnumerable<TEntity> eventObject, bool canCancel)
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the saving operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public SaveEventArgs(IEnumerable<TEntity> eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the saving operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public SaveEventArgs(IEnumerable<TEntity> eventObject, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public SaveEventArgs(TEntity eventObject, EventMessages eventMessages)
|
||||
: base(new List<TEntity> { eventObject }, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
/// <param name="eventMessages"></param>
|
||||
public SaveEventArgs(TEntity eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(new List<TEntity> { eventObject }, canCancel, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the saving operation
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
public SaveEventArgs(IEnumerable<TEntity> eventObject, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple/default transient messages factory
|
||||
/// </summary>
|
||||
internal class TransientMessagesFactory : IEventMessagesFactory
|
||||
{
|
||||
public EventMessages Get()
|
||||
{
|
||||
return new EventMessages();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception that is thrown if the umbraco application cannnot boot
|
||||
/// </summary>
|
||||
public class UmbracoStartupFailedException : Exception
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="T:System.Exception"/> class with a specified error message.
|
||||
/// </summary>
|
||||
/// <param name="message">The message that describes the error. </param>
|
||||
public UmbracoStartupFailedException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
-18
@@ -1,18 +1,18 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- Blocks public downloading of anything in this folder and sub folders -->
|
||||
|
||||
<configuration>
|
||||
<system.web>
|
||||
<httpHandlers>
|
||||
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
|
||||
</httpHandlers>
|
||||
</system.web>
|
||||
<system.webServer>
|
||||
<validation validateIntegratedModeConfiguration="false" />
|
||||
<handlers>
|
||||
<remove name="BlockViewHandler"/>
|
||||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!-- Blocks public downloading of anything in this folder and sub folders -->
|
||||
|
||||
<configuration>
|
||||
<system.web>
|
||||
<httpHandlers>
|
||||
<add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
|
||||
</httpHandlers>
|
||||
</system.web>
|
||||
<system.webServer>
|
||||
<validation validateIntegratedModeConfiguration="false" />
|
||||
<handlers>
|
||||
<remove name="BlockViewHandler"/>
|
||||
<add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Umbraco.Core.FileResources {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Files {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Files() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Umbraco.Core.FileResources.Files", typeof(Files).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to <?xml version="1.0"?>
|
||||
///
|
||||
///<!-- Blocks public downloading of anything in this folder and sub folders -->
|
||||
///
|
||||
///<configuration>
|
||||
/// <system.web>
|
||||
/// <httpHandlers>
|
||||
/// <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
|
||||
/// </httpHandlers>
|
||||
/// </system.web>
|
||||
/// <system.webServer>
|
||||
/// <validation validateIntegratedModeConfiguration="false" />
|
||||
/// <handlers>
|
||||
/// <remove name="BlockViewHandler"/>
|
||||
/// <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.H [rest of string was truncated]";.
|
||||
/// </summary>
|
||||
internal static string BlockingWebConfig {
|
||||
get {
|
||||
return ResourceManager.GetString("BlockingWebConfig", resourceCulture);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
|
||||
<data name="BlockingWebConfig" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||
<value>blockingweb.config;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -6,6 +6,7 @@ using System.IO;
|
||||
using System.Configuration;
|
||||
using System.Web;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web.Hosting;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -51,23 +52,39 @@ namespace Umbraco.Core.IO
|
||||
return VirtualPathUtility.ToAbsolute(virtualPath, SystemDirectories.Root);
|
||||
}
|
||||
|
||||
[Obsolete("Use Umbraco.Web.Templates.TemplateUtilities.ResolveUrlsFromTextString instead, this method on this class will be removed in future versions")]
|
||||
public static Attempt<string> TryResolveUrl(string virtualPath)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (virtualPath.StartsWith("~"))
|
||||
return Attempt.Succeed(virtualPath.Replace("~", SystemDirectories.Root).Replace("//", "/"));
|
||||
if (Uri.IsWellFormedUriString(virtualPath, UriKind.Absolute))
|
||||
return Attempt.Succeed(virtualPath);
|
||||
return Attempt.Succeed(VirtualPathUtility.ToAbsolute(virtualPath, SystemDirectories.Root));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return Attempt.Fail(virtualPath, ex);
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use Umbraco.Web.Templates.TemplateUtilities.ResolveUrlsFromTextString instead, this method on this class will be removed in future versions")]
|
||||
internal static string ResolveUrlsFromTextString(string text)
|
||||
{
|
||||
if (UmbracoConfig.For.UmbracoSettings().Content.ResolveUrlsFromTextString)
|
||||
{
|
||||
using (var timer = DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
|
||||
using (DisposableTimer.DebugDuration(typeof(IOHelper), "ResolveUrlsFromTextString starting", "ResolveUrlsFromTextString complete"))
|
||||
{
|
||||
// find all relative urls (ie. urls that contain ~)
|
||||
var tags = ResolveUrlPattern.Matches(text);
|
||||
LogHelper.Debug(typeof(IOHelper), "After regex: " + timer.Stopwatch.ElapsedMilliseconds + " matched: " + tags.Count);
|
||||
|
||||
foreach (Match tag in tags)
|
||||
{
|
||||
string url = "";
|
||||
if (tag.Groups[1].Success)
|
||||
url = tag.Groups[1].Value;
|
||||
|
||||
if (string.IsNullOrEmpty(url) == false)
|
||||
if (String.IsNullOrEmpty(url) == false)
|
||||
{
|
||||
string resolvedUrl = (url.Substring(0, 1) == "/") ? ResolveUrl(url.Substring(1)) : ResolveUrl(url);
|
||||
text = text.Replace(url, resolvedUrl);
|
||||
@@ -92,10 +109,10 @@ namespace Umbraco.Core.IO
|
||||
if (useHttpContext && HttpContext.Current != null)
|
||||
{
|
||||
//string retval;
|
||||
if (string.IsNullOrEmpty(path) == false && (path.StartsWith("~") || path.StartsWith(SystemDirectories.Root)))
|
||||
return System.Web.Hosting.HostingEnvironment.MapPath(path);
|
||||
if (String.IsNullOrEmpty(path) == false && (path.StartsWith("~") || path.StartsWith(SystemDirectories.Root)))
|
||||
return HostingEnvironment.MapPath(path);
|
||||
else
|
||||
return System.Web.Hosting.HostingEnvironment.MapPath("~/" + path.TrimStart('/'));
|
||||
return HostingEnvironment.MapPath("~/" + path.TrimStart('/'));
|
||||
}
|
||||
|
||||
var root = GetRootDirectorySafe();
|
||||
@@ -115,7 +132,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
string retval = ConfigurationManager.AppSettings[settingsKey];
|
||||
|
||||
if (string.IsNullOrEmpty(retval))
|
||||
if (String.IsNullOrEmpty(retval))
|
||||
retval = standardPath;
|
||||
|
||||
return retval.TrimEnd('/');
|
||||
@@ -135,12 +152,7 @@ namespace Umbraco.Core.IO
|
||||
/// <returns>A value indicating whether the filepath is valid.</returns>
|
||||
internal static bool VerifyEditPath(string filePath, string validDir)
|
||||
{
|
||||
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
filePath = MapPath(filePath);
|
||||
if (validDir.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
validDir = MapPath(validDir);
|
||||
|
||||
return filePath.StartsWith(validDir);
|
||||
return VerifyEditPath(filePath, new[] { validDir });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -165,15 +177,31 @@ namespace Umbraco.Core.IO
|
||||
/// <returns>A value indicating whether the filepath is valid.</returns>
|
||||
internal static bool VerifyEditPath(string filePath, IEnumerable<string> validDirs)
|
||||
{
|
||||
// this is called from ScriptRepository, PartialViewRepository, etc.
|
||||
// filePath is the fullPath (rooted, filesystem path, can be trusted)
|
||||
// validDirs are virtual paths (eg ~/Views)
|
||||
//
|
||||
// except that for templates, filePath actually is a virtual path
|
||||
|
||||
//TODO
|
||||
// what's below is dirty, there are too many ways to get the root dir, etc.
|
||||
// not going to fix everything today
|
||||
|
||||
var mappedRoot = MapPath(SystemDirectories.Root);
|
||||
if (filePath.StartsWith(mappedRoot) == false)
|
||||
filePath = MapPath(filePath);
|
||||
|
||||
// yes we can (see above)
|
||||
//// don't trust what we get, it may contain relative segments
|
||||
//filePath = Path.GetFullPath(filePath);
|
||||
|
||||
foreach (var dir in validDirs)
|
||||
{
|
||||
var validDir = dir;
|
||||
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
filePath = MapPath(filePath);
|
||||
if (validDir.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
if (validDir.StartsWith(mappedRoot) == false)
|
||||
validDir = MapPath(validDir);
|
||||
|
||||
if (filePath.StartsWith(validDir))
|
||||
if (PathStartsWith(filePath, validDir, Path.DirectorySeparatorChar))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -202,11 +230,8 @@ namespace Umbraco.Core.IO
|
||||
/// <returns>A value indicating whether the filepath is valid.</returns>
|
||||
internal static bool VerifyFileExtension(string filePath, List<string> validFileExtensions)
|
||||
{
|
||||
if (filePath.StartsWith(MapPath(SystemDirectories.Root)) == false)
|
||||
filePath = MapPath(filePath);
|
||||
var f = new FileInfo(filePath);
|
||||
|
||||
return validFileExtensions.Contains(f.Extension.Substring(1));
|
||||
var ext = Path.GetExtension(filePath);
|
||||
return ext != null && validFileExtensions.Contains(ext.TrimStart('.'));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -223,6 +248,16 @@ namespace Umbraco.Core.IO
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool PathStartsWith(string path, string root, char separator)
|
||||
{
|
||||
// either it is identical to root,
|
||||
// or it is root + separator + anything
|
||||
|
||||
if (path.StartsWith(root, StringComparison.OrdinalIgnoreCase) == false) return false;
|
||||
if (path.Length == root.Length) return true;
|
||||
if (path.Length < root.Length) return false;
|
||||
return path[root.Length] == separator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the path to the root of the application, by getting the path to where the assembly where this
|
||||
@@ -232,7 +267,7 @@ namespace Umbraco.Core.IO
|
||||
/// <returns></returns>
|
||||
internal static string GetRootDirectorySafe()
|
||||
{
|
||||
if (string.IsNullOrEmpty(_rootDir) == false)
|
||||
if (String.IsNullOrEmpty(_rootDir) == false)
|
||||
{
|
||||
return _rootDir;
|
||||
}
|
||||
@@ -241,7 +276,7 @@ namespace Umbraco.Core.IO
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
var baseDirectory = Path.GetDirectoryName(path);
|
||||
if (string.IsNullOrEmpty(baseDirectory))
|
||||
if (String.IsNullOrEmpty(baseDirectory))
|
||||
throw new Exception("No root directory could be resolved. Please ensure that your Umbraco solution is correctly configured.");
|
||||
|
||||
_rootDir = baseDirectory.Contains("bin")
|
||||
@@ -253,8 +288,8 @@ namespace Umbraco.Core.IO
|
||||
|
||||
internal static string GetRootDirectoryBinFolder()
|
||||
{
|
||||
string binFolder = string.Empty;
|
||||
if (string.IsNullOrEmpty(_rootDir))
|
||||
string binFolder = String.Empty;
|
||||
if (String.IsNullOrEmpty(_rootDir))
|
||||
{
|
||||
binFolder = Assembly.GetExecutingAssembly().GetAssemblyFile().Directory.FullName;
|
||||
return binFolder;
|
||||
@@ -298,5 +333,25 @@ namespace Umbraco.Core.IO
|
||||
// use string extensions
|
||||
return filePath.ToSafeFileName();
|
||||
}
|
||||
|
||||
public static void EnsurePathExists(string path)
|
||||
{
|
||||
var absolutePath = IOHelper.MapPath(path);
|
||||
if (Directory.Exists(absolutePath) == false)
|
||||
Directory.CreateDirectory(absolutePath);
|
||||
}
|
||||
|
||||
public static void EnsureFileExists(string path, string contents)
|
||||
{
|
||||
var absolutePath = IOHelper.MapPath(path);
|
||||
if (File.Exists(absolutePath) == false)
|
||||
{
|
||||
using (var writer = File.CreateText(absolutePath))
|
||||
{
|
||||
writer.Write(contents);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,450 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
internal class MasterPageHelper
|
||||
{
|
||||
private readonly IFileSystem _masterPageFileSystem;
|
||||
internal static readonly string DefaultMasterTemplate = SystemDirectories.Umbraco + "/masterpages/default.master";
|
||||
//private static readonly char[] NewLineChars = Environment.NewLine.ToCharArray();
|
||||
|
||||
public MasterPageHelper(IFileSystem masterPageFileSystem)
|
||||
{
|
||||
if (masterPageFileSystem == null) throw new ArgumentNullException("masterPageFileSystem");
|
||||
_masterPageFileSystem = masterPageFileSystem;
|
||||
}
|
||||
|
||||
public bool MasterPageExists(ITemplate t)
|
||||
{
|
||||
return _masterPageFileSystem.FileExists(GetFilePath(t));
|
||||
}
|
||||
|
||||
[Obsolete("This is only used for legacy purposes and will be removed in future versions")]
|
||||
internal string GetPhysicalFilePath(ITemplate t)
|
||||
{
|
||||
return _masterPageFileSystem.GetFullPath(GetFilePath(t.Alias));
|
||||
}
|
||||
|
||||
private string GetFilePath(ITemplate t)
|
||||
{
|
||||
return GetFilePath(t.Alias);
|
||||
}
|
||||
|
||||
private string GetFilePath(string alias)
|
||||
{
|
||||
return alias + ".master";
|
||||
}
|
||||
|
||||
public string CreateMasterPage(ITemplate t, ITemplateRepository templateRepo, bool overWrite = false)
|
||||
{
|
||||
string masterpageContent = "";
|
||||
|
||||
var filePath = GetFilePath(t);
|
||||
if (_masterPageFileSystem.FileExists(filePath) == false || overWrite)
|
||||
{
|
||||
masterpageContent = t.Content.IsNullOrWhiteSpace() ? CreateDefaultMasterPageContent(t, templateRepo) : t.Content;
|
||||
|
||||
var data = Encoding.UTF8.GetBytes(masterpageContent);
|
||||
var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
|
||||
|
||||
using (var ms = new MemoryStream(withBom))
|
||||
{
|
||||
_masterPageFileSystem.AddFile(filePath, ms, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var s = _masterPageFileSystem.OpenFile(filePath))
|
||||
using (var tr = new StreamReader(s, Encoding.UTF8))
|
||||
{
|
||||
masterpageContent = tr.ReadToEnd();
|
||||
tr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return masterpageContent;
|
||||
}
|
||||
|
||||
//internal string GetFileContents(ITemplate t)
|
||||
//{
|
||||
// var masterpageContent = "";
|
||||
// if (_masterPageFileSystem.FileExists(GetFilePath(t)))
|
||||
// {
|
||||
// using (var s = _masterPageFileSystem.OpenFile(GetFilePath(t)))
|
||||
// using (var tr = new StreamReader(s))
|
||||
// {
|
||||
// masterpageContent = tr.ReadToEnd();
|
||||
// tr.Close();
|
||||
// }
|
||||
// }
|
||||
|
||||
// return masterpageContent;
|
||||
//}
|
||||
|
||||
public string UpdateMasterPageFile(ITemplate t, string currentAlias, ITemplateRepository templateRepo)
|
||||
{
|
||||
var template = UpdateMasterPageContent(t, currentAlias);
|
||||
UpdateChildTemplates(t, currentAlias, templateRepo);
|
||||
var filePath = GetFilePath(t);
|
||||
|
||||
var data = Encoding.UTF8.GetBytes(template);
|
||||
var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
|
||||
|
||||
using (var ms = new MemoryStream(withBom))
|
||||
{
|
||||
_masterPageFileSystem.AddFile(filePath, ms, true);
|
||||
}
|
||||
return template;
|
||||
}
|
||||
|
||||
private string CreateDefaultMasterPageContent(ITemplate template, ITemplateRepository templateRepo)
|
||||
{
|
||||
var design = new StringBuilder();
|
||||
design.Append(GetMasterPageHeader(template) + Environment.NewLine);
|
||||
|
||||
if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
var master = templateRepo.Get(template.MasterTemplateAlias);
|
||||
if (master != null)
|
||||
{
|
||||
foreach (var cpId in GetContentPlaceholderIds(master))
|
||||
{
|
||||
design.Append("<asp:content ContentPlaceHolderId=\"" + cpId + "\" runat=\"server\">" +
|
||||
Environment.NewLine +
|
||||
Environment.NewLine +
|
||||
"</asp:content>" +
|
||||
Environment.NewLine +
|
||||
Environment.NewLine);
|
||||
}
|
||||
|
||||
return design.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
design.Append(GetMasterContentElement(template) + Environment.NewLine);
|
||||
design.Append(template.Content + Environment.NewLine);
|
||||
design.Append("</asp:Content>" + Environment.NewLine);
|
||||
|
||||
return design.ToString();
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetContentPlaceholderIds(ITemplate template)
|
||||
{
|
||||
var retVal = new List<string>();
|
||||
|
||||
var mp = template.Content;
|
||||
var path = "<asp:ContentPlaceHolder+(\\s+[a-zA-Z]+\\s*=\\s*(\"([^\"]*)\"|'([^']*)'))*\\s*/?>";
|
||||
var r = new Regex(path, RegexOptions.IgnoreCase);
|
||||
var m = r.Match(mp);
|
||||
|
||||
while (m.Success)
|
||||
{
|
||||
var cc = m.Groups[3].Captures;
|
||||
retVal.AddRange(cc.Cast<Capture>().Where(c => c.Value != "server").Select(c => c.Value));
|
||||
|
||||
m = m.NextMatch();
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
private static string UpdateMasterPageContent(ITemplate template, string currentAlias)
|
||||
{
|
||||
var masterPageContent = template.Content;
|
||||
|
||||
if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias)
|
||||
{
|
||||
var masterHeader =
|
||||
masterPageContent.Substring(0, masterPageContent.IndexOf("%>", StringComparison.Ordinal) + 2).Trim(
|
||||
Environment.NewLine.ToCharArray());
|
||||
|
||||
// find the masterpagefile attribute
|
||||
var m = Regex.Matches(masterHeader, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
|
||||
RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
foreach (Match attributeSet in m)
|
||||
{
|
||||
if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile")
|
||||
{
|
||||
// validate the masterpagefile
|
||||
var currentMasterPageFile = attributeSet.Groups["attributeValue"].Value;
|
||||
var currentMasterTemplateFile = ParentTemplatePath(template);
|
||||
|
||||
if (currentMasterPageFile != currentMasterTemplateFile)
|
||||
{
|
||||
masterPageContent =
|
||||
masterPageContent.Replace(
|
||||
attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"",
|
||||
attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile +
|
||||
"\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return masterPageContent;
|
||||
}
|
||||
|
||||
private void UpdateChildTemplates(ITemplate template, string currentAlias, ITemplateRepository templateRepo)
|
||||
{
|
||||
//if we have a Old Alias if the alias and therefor the masterpage file name has changed...
|
||||
//so before we save the new masterfile, we'll clear the old one, so we don't up with
|
||||
//Unused masterpage files
|
||||
if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias)
|
||||
{
|
||||
//Ensure that child templates have the right master masterpage file name
|
||||
if (template.IsMasterTemplate)
|
||||
{
|
||||
var children = templateRepo.GetChildren(template.Id);
|
||||
foreach (var t in children)
|
||||
UpdateMasterPageFile(t, null, templateRepo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//private void SaveDesignToFile(ITemplate t, string currentAlias, string design)
|
||||
//{
|
||||
// //kill the old file..
|
||||
// if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != t.Alias)
|
||||
// {
|
||||
// var oldFile =
|
||||
// IOHelper.MapPath(SystemDirectories.Masterpages + "/" + currentAlias.Replace(" ", "") + ".master");
|
||||
// if (System.IO.File.Exists(oldFile))
|
||||
// System.IO.File.Delete(oldFile);
|
||||
// }
|
||||
|
||||
// // save the file in UTF-8
|
||||
// System.IO.File.WriteAllText(GetFilePath(t), design, Encoding.UTF8);
|
||||
//}
|
||||
|
||||
//internal static void RemoveMasterPageFile(string alias)
|
||||
//{
|
||||
// if (string.IsNullOrWhiteSpace(alias) == false)
|
||||
// {
|
||||
// string file = IOHelper.MapPath(SystemDirectories.Masterpages + "/" + alias.Replace(" ", "") + ".master");
|
||||
// if (System.IO.File.Exists(file))
|
||||
// System.IO.File.Delete(file);
|
||||
// }
|
||||
//}
|
||||
|
||||
//internal string SaveTemplateToFile(ITemplate template, string currentAlias, ITemplateRepository templateRepo)
|
||||
//{
|
||||
// var masterPageContent = template.Content;
|
||||
// if (IsMasterPageSyntax(masterPageContent) == false)
|
||||
// masterPageContent = ConvertToMasterPageSyntax(template);
|
||||
|
||||
// // Add header to master page if it doesn't exist
|
||||
// if (masterPageContent.TrimStart().StartsWith("<%@") == false)
|
||||
// {
|
||||
// masterPageContent = GetMasterPageHeader(template) + Environment.NewLine + masterPageContent;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // verify that the masterpage attribute is the same as the masterpage
|
||||
// var masterHeader =
|
||||
// masterPageContent.Substring(0, masterPageContent.IndexOf("%>", StringComparison.Ordinal) + 2).Trim(NewLineChars);
|
||||
|
||||
// // find the masterpagefile attribute
|
||||
// var m = Regex.Matches(masterHeader, "(?<attributeName>\\S*)=\"(?<attributeValue>[^\"]*)\"",
|
||||
// RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
// foreach (Match attributeSet in m)
|
||||
// {
|
||||
// if (attributeSet.Groups["attributeName"].Value.ToLower() == "masterpagefile")
|
||||
// {
|
||||
// // validate the masterpagefile
|
||||
// var currentMasterPageFile = attributeSet.Groups["attributeValue"].Value;
|
||||
// var currentMasterTemplateFile = ParentTemplatePath(template);
|
||||
|
||||
// if (currentMasterPageFile != currentMasterTemplateFile)
|
||||
// {
|
||||
// masterPageContent =
|
||||
// masterPageContent.Replace(
|
||||
// attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterPageFile + "\"",
|
||||
// attributeSet.Groups["attributeName"].Value + "=\"" + currentMasterTemplateFile +
|
||||
// "\"");
|
||||
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// //we have a Old Alias if the alias and therefor the masterpage file name has changed...
|
||||
// //so before we save the new masterfile, we'll clear the old one, so we don't up with
|
||||
// //Unused masterpage files
|
||||
// if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != template.Alias)
|
||||
// {
|
||||
|
||||
// //Ensure that child templates have the right master masterpage file name
|
||||
// if (template.IsMasterTemplate)
|
||||
// {
|
||||
// var children = templateRepo.GetChildren(template.Id);
|
||||
|
||||
// foreach (var t in children)
|
||||
// UpdateMasterPageFile(t, null, templateRepo);
|
||||
// }
|
||||
|
||||
// //then kill the old file..
|
||||
// var oldFile = GetFilePath(currentAlias);
|
||||
// if (_masterPageFileSystem.FileExists(oldFile))
|
||||
// _masterPageFileSystem.DeleteFile(oldFile);
|
||||
// }
|
||||
|
||||
// // save the file in UTF-8
|
||||
// System.IO.File.WriteAllText(GetFilePath(template), masterPageContent, Encoding.UTF8);
|
||||
|
||||
// return masterPageContent;
|
||||
//}
|
||||
|
||||
//internal static string ConvertToMasterPageSyntax(ITemplate template)
|
||||
//{
|
||||
// string masterPageContent = GetMasterContentElement(template) + Environment.NewLine;
|
||||
|
||||
// masterPageContent += template.Content;
|
||||
|
||||
// // Parse the design for getitems
|
||||
// masterPageContent = EnsureMasterPageSyntax(template.Alias, masterPageContent);
|
||||
|
||||
// // append ending asp:content element
|
||||
// masterPageContent += Environment.NewLine + "</asp:Content>" + Environment.NewLine;
|
||||
|
||||
// return masterPageContent;
|
||||
//}
|
||||
|
||||
public static bool IsMasterPageSyntax(string code)
|
||||
{
|
||||
return Regex.IsMatch(code, @"<%@\s*Master", RegexOptions.IgnoreCase) ||
|
||||
code.InvariantContains("<umbraco:Item") || code.InvariantContains("<asp:") || code.InvariantContains("<umbraco:Macro");
|
||||
}
|
||||
|
||||
private static string GetMasterPageHeader(ITemplate template)
|
||||
{
|
||||
return String.Format("<%@ Master Language=\"C#\" MasterPageFile=\"{0}\" AutoEventWireup=\"true\" %>", ParentTemplatePath(template)) + Environment.NewLine;
|
||||
}
|
||||
|
||||
private static string ParentTemplatePath(ITemplate template)
|
||||
{
|
||||
var masterTemplate = DefaultMasterTemplate;
|
||||
if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false)
|
||||
masterTemplate = SystemDirectories.Masterpages + "/" + template.MasterTemplateAlias + ".master";
|
||||
|
||||
return masterTemplate;
|
||||
}
|
||||
|
||||
private static string GetMasterContentElement(ITemplate template)
|
||||
{
|
||||
if (template.MasterTemplateAlias.IsNullOrWhiteSpace() == false)
|
||||
{
|
||||
string masterAlias = template.MasterTemplateAlias;
|
||||
return
|
||||
String.Format("<asp:Content ContentPlaceHolderID=\"{0}ContentPlaceHolder\" runat=\"server\">", masterAlias);
|
||||
}
|
||||
else
|
||||
return
|
||||
String.Format("<asp:Content ContentPlaceHolderID=\"ContentPlaceHolderDefault\" runat=\"server\">");
|
||||
|
||||
}
|
||||
|
||||
//internal static string EnsureMasterPageSyntax(string templateAlias, string masterPageContent)
|
||||
//{
|
||||
// ReplaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", true);
|
||||
// ReplaceElement(ref masterPageContent, "?UMBRACO_GETITEM", "umbraco:Item", false);
|
||||
|
||||
// // Parse the design for macros
|
||||
// ReplaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", true);
|
||||
// ReplaceElement(ref masterPageContent, "?UMBRACO_MACRO", "umbraco:Macro", false);
|
||||
|
||||
// // Parse the design for load childs
|
||||
// masterPageContent = masterPageContent.Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD/>", CreateDefaultPlaceHolder(templateAlias))
|
||||
// .Replace("<?UMBRACO_TEMPLATE_LOAD_CHILD />", CreateDefaultPlaceHolder(templateAlias));
|
||||
// // Parse the design for aspnet forms
|
||||
// GetAspNetMasterPageForm(ref masterPageContent, templateAlias);
|
||||
// masterPageContent = masterPageContent.Replace("</?ASPNET_FORM>", "</form>");
|
||||
// // Parse the design for aspnet heads
|
||||
// masterPageContent = masterPageContent.Replace("</ASPNET_HEAD>", String.Format("<head id=\"{0}Head\" runat=\"server\">", templateAlias.Replace(" ", "")));
|
||||
// masterPageContent = masterPageContent.Replace("</?ASPNET_HEAD>", "</head>");
|
||||
// return masterPageContent;
|
||||
//}
|
||||
|
||||
|
||||
//private static void GetAspNetMasterPageForm(ref string design, string templateAlias)
|
||||
//{
|
||||
// var formElement = Regex.Match(design, GetElementRegExp("?ASPNET_FORM", false), RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
// if (string.IsNullOrEmpty(formElement.Value) == false)
|
||||
// {
|
||||
// string formReplace = String.Format("<form id=\"{0}Form\" runat=\"server\">", templateAlias.Replace(" ", ""));
|
||||
// if (formElement.Groups.Count == 0)
|
||||
// {
|
||||
// formReplace += "<asp:scriptmanager runat=\"server\"></asp:scriptmanager>";
|
||||
// }
|
||||
// design = design.Replace(formElement.Value, formReplace);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private static string CreateDefaultPlaceHolder(string templateAlias)
|
||||
//{
|
||||
// return String.Format("<asp:ContentPlaceHolder ID=\"{0}ContentPlaceHolder\" runat=\"server\"></asp:ContentPlaceHolder>", templateAlias.Replace(" ", ""));
|
||||
//}
|
||||
|
||||
//private static void ReplaceElement(ref string design, string elementName, string newElementName, bool checkForQuotes)
|
||||
//{
|
||||
// var m =
|
||||
// Regex.Matches(design, GetElementRegExp(elementName, checkForQuotes),
|
||||
// RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace);
|
||||
|
||||
// foreach (Match match in m)
|
||||
// {
|
||||
// GroupCollection groups = match.Groups;
|
||||
|
||||
// // generate new element (compensate for a closing trail on single elements ("/"))
|
||||
// string elementAttributes = groups[1].Value;
|
||||
// // test for macro alias
|
||||
// if (elementName == "?UMBRACO_MACRO")
|
||||
// {
|
||||
// var tags = XmlHelper.GetAttributesFromElement(match.Value);
|
||||
// if (tags["macroAlias"] != null)
|
||||
// elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroAlias"]) + elementAttributes;
|
||||
// else if (tags["macroalias"] != null)
|
||||
// elementAttributes = String.Format(" Alias=\"{0}\"", tags["macroalias"]) + elementAttributes;
|
||||
// }
|
||||
// string newElement = "<" + newElementName + " runat=\"server\" " + elementAttributes.Trim() + ">";
|
||||
// if (elementAttributes.EndsWith("/"))
|
||||
// {
|
||||
// elementAttributes = elementAttributes.Substring(0, elementAttributes.Length - 1);
|
||||
// }
|
||||
// else if (groups[0].Value.StartsWith("</"))
|
||||
// // It's a closing element, so generate that instead of a starting element
|
||||
// newElement = "</" + newElementName + ">";
|
||||
|
||||
// if (checkForQuotes)
|
||||
// {
|
||||
// // if it's inside quotes, we'll change element attribute quotes to single quotes
|
||||
// newElement = newElement.Replace("\"", "'");
|
||||
// newElement = String.Format("\"{0}\"", newElement);
|
||||
// }
|
||||
// design = design.Replace(match.Value, newElement);
|
||||
// }
|
||||
//}
|
||||
|
||||
//private static string GetElementRegExp(string elementName, bool checkForQuotes)
|
||||
//{
|
||||
// if (checkForQuotes)
|
||||
// return String.Format("\"<[^>\\s]*\\b{0}(\\b[^>]*)>\"", elementName);
|
||||
// else
|
||||
// return String.Format("<[^>\\s]*\\b{0}(\\b[^>]*)>", elementName);
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
@@ -9,17 +8,27 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
public class PhysicalFileSystem : IFileSystem
|
||||
{
|
||||
internal string RootPath { get; private set; }
|
||||
// the rooted, filesystem path, using directory separator chars, NOT ending with a separator
|
||||
// eg "c:" or "c:\path\to\site" or "\\server\path"
|
||||
private readonly string _rootPath;
|
||||
|
||||
// the ??? url, using url separator chars, NOT ending with a separator
|
||||
// eg "" (?) or "/Scripts" or ???
|
||||
private readonly string _rootUrl;
|
||||
|
||||
public PhysicalFileSystem(string virtualRoot)
|
||||
{
|
||||
if (virtualRoot == null) throw new ArgumentNullException("virtualRoot");
|
||||
if (!virtualRoot.StartsWith("~/"))
|
||||
if (virtualRoot.StartsWith("~/") == false)
|
||||
throw new ArgumentException("The virtualRoot argument must be a virtual path and start with '~/'");
|
||||
|
||||
RootPath = IOHelper.MapPath(virtualRoot);
|
||||
_rootPath = IOHelper.MapPath(virtualRoot);
|
||||
_rootPath = EnsureDirectorySeparatorChar(_rootPath);
|
||||
_rootPath = _rootPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
|
||||
_rootUrl = IOHelper.ResolveUrl(virtualRoot);
|
||||
_rootUrl = EnsureUrlSeparatorChar(_rootUrl);
|
||||
_rootUrl = _rootUrl.TrimEnd('/');
|
||||
}
|
||||
|
||||
public PhysicalFileSystem(string rootPath, string rootUrl)
|
||||
@@ -33,18 +42,31 @@ namespace Umbraco.Core.IO
|
||||
if (rootPath.StartsWith("~/"))
|
||||
throw new ArgumentException("The rootPath argument cannot be a virtual path and cannot start with '~/'");
|
||||
|
||||
RootPath = rootPath;
|
||||
_rootUrl = rootUrl;
|
||||
// rootPath should be... rooted, as in, it's a root path!
|
||||
// but the test suite App.config cannot really "root" anything so we'll have to do it here
|
||||
|
||||
//var localRoot = AppDomain.CurrentDomain.BaseDirectory;
|
||||
var localRoot = IOHelper.GetRootDirectorySafe();
|
||||
if (Path.IsPathRooted(rootPath) == false)
|
||||
{
|
||||
rootPath = Path.Combine(localRoot, rootPath);
|
||||
}
|
||||
|
||||
rootPath = EnsureDirectorySeparatorChar(rootPath);
|
||||
rootUrl = EnsureUrlSeparatorChar(rootUrl);
|
||||
|
||||
_rootPath = rootPath.TrimEnd(Path.DirectorySeparatorChar);
|
||||
_rootUrl = rootUrl.TrimEnd('/');
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetDirectories(string path)
|
||||
{
|
||||
path = EnsureTrailingSeparator(GetFullPath(path));
|
||||
var fullPath = GetFullPath(path);
|
||||
|
||||
try
|
||||
{
|
||||
if (Directory.Exists(path))
|
||||
return Directory.EnumerateDirectories(path).Select(GetRelativePath);
|
||||
if (Directory.Exists(fullPath))
|
||||
return Directory.EnumerateDirectories(fullPath).Select(GetRelativePath);
|
||||
}
|
||||
catch (UnauthorizedAccessException ex)
|
||||
{
|
||||
@@ -65,12 +87,13 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public void DeleteDirectory(string path, bool recursive)
|
||||
{
|
||||
if (!DirectoryExists(path))
|
||||
var fullPath = GetFullPath(path);
|
||||
if (Directory.Exists(fullPath) == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
Directory.Delete(GetFullPath(path), recursive);
|
||||
Directory.Delete(fullPath, recursive);
|
||||
}
|
||||
catch (DirectoryNotFoundException ex)
|
||||
{
|
||||
@@ -80,7 +103,8 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public bool DirectoryExists(string path)
|
||||
{
|
||||
return Directory.Exists(GetFullPath(path));
|
||||
var fullPath = GetFullPath(path);
|
||||
return Directory.Exists(fullPath);
|
||||
}
|
||||
|
||||
public void AddFile(string path, Stream stream)
|
||||
@@ -90,17 +114,17 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public void AddFile(string path, Stream stream, bool overrideIfExists)
|
||||
{
|
||||
var fsRelativePath = GetRelativePath(path);
|
||||
var fullPath = GetFullPath(path);
|
||||
var exists = File.Exists(fullPath);
|
||||
if (exists && overrideIfExists == false)
|
||||
throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
|
||||
|
||||
var exists = FileExists(fsRelativePath);
|
||||
if (exists && overrideIfExists == false) throw new InvalidOperationException(string.Format("A file at path '{0}' already exists", path));
|
||||
|
||||
EnsureDirectory(Path.GetDirectoryName(fsRelativePath));
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(fullPath)); // ensure it exists
|
||||
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, 0);
|
||||
|
||||
using (var destination = (Stream)File.Create(GetFullPath(fsRelativePath)))
|
||||
using (var destination = (Stream)File.Create(fullPath))
|
||||
stream.CopyTo(destination);
|
||||
}
|
||||
|
||||
@@ -111,9 +135,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public IEnumerable<string> GetFiles(string path, string filter)
|
||||
{
|
||||
var fsRelativePath = GetRelativePath(path);
|
||||
|
||||
var fullPath = EnsureTrailingSeparator(GetFullPath(fsRelativePath));
|
||||
var fullPath = GetFullPath(path);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -140,12 +162,13 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public void DeleteFile(string path)
|
||||
{
|
||||
if (!FileExists(path))
|
||||
var fullPath = GetFullPath(path);
|
||||
if (File.Exists(fullPath) == false)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
File.Delete(GetFullPath(path));
|
||||
File.Delete(fullPath);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
@@ -155,39 +178,86 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public bool FileExists(string path)
|
||||
{
|
||||
return File.Exists(GetFullPath(path));
|
||||
var fullpath = GetFullPath(path);
|
||||
return File.Exists(fullpath);
|
||||
}
|
||||
|
||||
// beware, many things depend on how the GetRelative/AbsolutePath methods work!
|
||||
|
||||
/// <summary>
|
||||
/// Gets the relative path.
|
||||
/// </summary>
|
||||
/// <param name="fullPathOrUrl">The full path or url.</param>
|
||||
/// <returns>The path, relative to this filesystem's root.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The relative path is relative to this filesystem's root, not starting with any
|
||||
/// directory separator. If input was recognized as a url (path), then output uses url (path) separator
|
||||
/// chars.</para>
|
||||
/// </remarks>
|
||||
public string GetRelativePath(string fullPathOrUrl)
|
||||
{
|
||||
var relativePath = fullPathOrUrl
|
||||
.TrimStart(_rootUrl)
|
||||
.Replace('/', Path.DirectorySeparatorChar)
|
||||
.TrimStart(RootPath)
|
||||
.TrimStart(Path.DirectorySeparatorChar);
|
||||
// test url
|
||||
var path = fullPathOrUrl.Replace('\\', '/'); // ensure url separator char
|
||||
|
||||
return relativePath;
|
||||
if (IOHelper.PathStartsWith(path, _rootUrl, '/')) // if it starts with the root url...
|
||||
return path.Substring(_rootUrl.Length) // strip it
|
||||
.TrimStart('/'); // it's relative
|
||||
|
||||
// test path
|
||||
path = EnsureDirectorySeparatorChar(fullPathOrUrl);
|
||||
|
||||
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar)) // if it starts with the root path
|
||||
return path.Substring(_rootPath.Length) // strip it
|
||||
.TrimStart(Path.DirectorySeparatorChar); // it's relative
|
||||
|
||||
// unchanged - including separators
|
||||
return fullPathOrUrl;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path.
|
||||
/// </summary>
|
||||
/// <param name="path">The full or relative path.</param>
|
||||
/// <returns>The full path.</returns>
|
||||
/// <remarks>
|
||||
/// <para>On the physical filesystem, the full path is the rooted (ie non-relative), safe (ie within this
|
||||
/// filesystem's root) path. All separators are converted to Path.DirectorySeparatorChar.</para>
|
||||
/// </remarks>
|
||||
public string GetFullPath(string path)
|
||||
{
|
||||
//if the path starts with a '/' then it's most likely not a FS relative path which is required so convert it
|
||||
if (path.StartsWith("/"))
|
||||
{
|
||||
path = GetRelativePath(path);
|
||||
}
|
||||
// normalize
|
||||
var opath = path;
|
||||
path = EnsureDirectorySeparatorChar(path);
|
||||
|
||||
return !path.StartsWith(RootPath)
|
||||
? Path.Combine(RootPath, path)
|
||||
: path;
|
||||
// not sure what we are doing here - so if input starts with a (back) slash,
|
||||
// we assume it's not a FS relative path and we try to convert it... but it
|
||||
// really makes little sense?
|
||||
if (path.StartsWith(Path.DirectorySeparatorChar.ToString()))
|
||||
path = GetRelativePath(path);
|
||||
|
||||
// if already a full path, return
|
||||
if (IOHelper.PathStartsWith(path, _rootPath, Path.DirectorySeparatorChar))
|
||||
return path;
|
||||
|
||||
// else combine and sanitize, ie GetFullPath will take care of any relative
|
||||
// segments in path, eg '../../foo.tmp' - it may throw a SecurityException
|
||||
// if the combined path reaches illegal parts of the filesystem
|
||||
var fpath = Path.Combine(_rootPath, path);
|
||||
fpath = Path.GetFullPath(fpath);
|
||||
|
||||
// at that point, path is within legal parts of the filesystem, ie we have
|
||||
// permissions to reach that path, but it may nevertheless be outside of
|
||||
// our root path, due to relative segments, so better check
|
||||
if (IOHelper.PathStartsWith(fpath, _rootPath, Path.DirectorySeparatorChar))
|
||||
return fpath;
|
||||
|
||||
throw new FileSecurityException("File '" + opath + "' is outside this filesystem's root.");
|
||||
}
|
||||
|
||||
public string GetUrl(string path)
|
||||
{
|
||||
return _rootUrl.TrimEnd("/") + "/" + path
|
||||
.TrimStart(Path.DirectorySeparatorChar)
|
||||
.Replace(Path.DirectorySeparatorChar, '/')
|
||||
.TrimEnd("/");
|
||||
path = EnsureUrlSeparatorChar(path).Trim('/');
|
||||
return _rootUrl + "/" + path;
|
||||
}
|
||||
|
||||
public DateTimeOffset GetLastModified(string path)
|
||||
@@ -214,9 +284,19 @@ namespace Umbraco.Core.IO
|
||||
|
||||
protected string EnsureTrailingSeparator(string path)
|
||||
{
|
||||
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture), StringComparison.Ordinal))
|
||||
path = path + Path.DirectorySeparatorChar;
|
||||
return path.EnsureEndsWith(Path.DirectorySeparatorChar);
|
||||
}
|
||||
|
||||
protected string EnsureDirectorySeparatorChar(string path)
|
||||
{
|
||||
path = path.Replace('/', Path.DirectorySeparatorChar);
|
||||
path = path.Replace('\\', Path.DirectorySeparatorChar);
|
||||
return path;
|
||||
}
|
||||
|
||||
protected string EnsureUrlSeparatorChar(string path)
|
||||
{
|
||||
path = path.Replace('\\', '/');
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
public class SystemFiles
|
||||
{
|
||||
|
||||
[Obsolete("This file is no longer used and should not be accessed!")]
|
||||
public static string AccessXml
|
||||
{
|
||||
get
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Models;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
internal class ViewHelper
|
||||
{
|
||||
private readonly IFileSystem _viewFileSystem;
|
||||
|
||||
public ViewHelper(IFileSystem viewFileSystem)
|
||||
{
|
||||
if (viewFileSystem == null) throw new ArgumentNullException("viewFileSystem");
|
||||
_viewFileSystem = viewFileSystem;
|
||||
}
|
||||
|
||||
internal bool ViewExists(ITemplate t)
|
||||
{
|
||||
return _viewFileSystem.FileExists(ViewPath(t.Alias));
|
||||
}
|
||||
|
||||
[Obsolete("This is only used for legacy purposes and will be removed in future versions")]
|
||||
internal string GetPhysicalFilePath(ITemplate t)
|
||||
{
|
||||
return _viewFileSystem.GetFullPath(ViewPath(t.Alias));
|
||||
}
|
||||
|
||||
internal string GetFileContents(ITemplate t)
|
||||
{
|
||||
string viewContent = "";
|
||||
string path = ViewPath(t.Alias);
|
||||
|
||||
if (_viewFileSystem.FileExists(path))
|
||||
{
|
||||
using (var tr = new StreamReader(_viewFileSystem.OpenFile(path)))
|
||||
{
|
||||
viewContent = tr.ReadToEnd();
|
||||
tr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return viewContent;
|
||||
}
|
||||
|
||||
public string CreateView(ITemplate t, bool overWrite = false)
|
||||
{
|
||||
string viewContent;
|
||||
string path = ViewPath(t.Alias);
|
||||
|
||||
if (_viewFileSystem.FileExists(path) == false || overWrite)
|
||||
{
|
||||
viewContent = SaveTemplateToFile(t);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var tr = new StreamReader(_viewFileSystem.OpenFile(path)))
|
||||
{
|
||||
viewContent = tr.ReadToEnd();
|
||||
tr.Close();
|
||||
}
|
||||
}
|
||||
|
||||
return viewContent;
|
||||
}
|
||||
|
||||
internal static string GetDefaultFileContent(string layoutPageAlias = null)
|
||||
{
|
||||
var design = @"@inherits Umbraco.Web.Mvc.UmbracoTemplatePage
|
||||
@{
|
||||
Layout = null;
|
||||
}";
|
||||
|
||||
if (layoutPageAlias.IsNullOrWhiteSpace() == false)
|
||||
design = design.Replace("null", string.Format("\"{0}.cshtml\"", layoutPageAlias));
|
||||
|
||||
return design;
|
||||
}
|
||||
|
||||
private string SaveTemplateToFile(ITemplate template)
|
||||
{
|
||||
var design = template.Content.IsNullOrWhiteSpace() ? EnsureInheritedLayout(template) : template.Content;
|
||||
var path = ViewPath(template.Alias);
|
||||
|
||||
var data = Encoding.UTF8.GetBytes(design);
|
||||
var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
|
||||
|
||||
using (var ms = new MemoryStream(withBom))
|
||||
{
|
||||
_viewFileSystem.AddFile(path, ms, true);
|
||||
}
|
||||
|
||||
return design;
|
||||
}
|
||||
|
||||
public string UpdateViewFile(ITemplate t, string currentAlias = null)
|
||||
{
|
||||
var path = ViewPath(t.Alias);
|
||||
|
||||
if (string.IsNullOrEmpty(currentAlias) == false && currentAlias != t.Alias)
|
||||
{
|
||||
//then kill the old file..
|
||||
var oldFile = ViewPath(currentAlias);
|
||||
if (_viewFileSystem.FileExists(oldFile))
|
||||
_viewFileSystem.DeleteFile(oldFile);
|
||||
}
|
||||
|
||||
var data = Encoding.UTF8.GetBytes(t.Content);
|
||||
var withBom = Encoding.UTF8.GetPreamble().Concat(data).ToArray();
|
||||
|
||||
using (var ms = new MemoryStream(withBom))
|
||||
{
|
||||
_viewFileSystem.AddFile(path, ms, true);
|
||||
}
|
||||
return t.Content;
|
||||
}
|
||||
|
||||
internal void RemoveViewFile(string alias)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(alias) == false)
|
||||
{
|
||||
var file = ViewPath(alias);
|
||||
if (_viewFileSystem.FileExists(file))
|
||||
_viewFileSystem.DeleteFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
public string ViewPath(string alias)
|
||||
{
|
||||
return _viewFileSystem.GetRelativePath(alias.Replace(" ", "") + ".cshtml");
|
||||
|
||||
//return SystemDirectories.MvcViews + "/" + alias.Replace(" ", "") + ".cshtml";
|
||||
}
|
||||
|
||||
private string EnsureInheritedLayout(ITemplate template)
|
||||
{
|
||||
string design = template.Content;
|
||||
|
||||
if (string.IsNullOrEmpty(design))
|
||||
{
|
||||
design = GetDefaultFileContent(template.MasterTemplateAlias);
|
||||
}
|
||||
|
||||
return design;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Allows for outputting a normalized appdomainappid token in a log format
|
||||
/// </summary>
|
||||
public sealed class AppDomainTokenConverter : log4net.Util.PatternConverter
|
||||
{
|
||||
protected override void Convert(TextWriter writer, object state)
|
||||
{
|
||||
writer.Write(HttpRuntime.AppDomainAppId.ReplaceNonAlphanumericChars(string.Empty));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
using System;
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Util;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <remarks>
|
||||
/// Based on https://github.com/cjbhaines/Log4Net.Async
|
||||
/// </remarks>
|
||||
public abstract class AsyncForwardingAppenderBase : ForwardingAppender
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private const FixFlags DefaultFixFlags = FixFlags.Partial;
|
||||
private FixFlags _fixFlags = DefaultFixFlags;
|
||||
private LoggingEventHelper _loggingEventHelper;
|
||||
|
||||
#endregion Private Members
|
||||
|
||||
#region Properties
|
||||
|
||||
public FixFlags Fix
|
||||
{
|
||||
get { return _fixFlags; }
|
||||
set { SetFixFlags(value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The logger name that will be used for logging internal errors.
|
||||
/// </summary>
|
||||
protected abstract string InternalLoggerName { get; }
|
||||
|
||||
public abstract int? BufferSize { get; set; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
_loggingEventHelper = new LoggingEventHelper(InternalLoggerName, DefaultFixFlags);
|
||||
InitializeAppenders();
|
||||
}
|
||||
|
||||
#region Appender Management
|
||||
|
||||
public override void AddAppender(IAppender newAppender)
|
||||
{
|
||||
base.AddAppender(newAppender);
|
||||
SetAppenderFixFlags(newAppender);
|
||||
}
|
||||
|
||||
private void SetFixFlags(FixFlags newFixFlags)
|
||||
{
|
||||
if (newFixFlags != _fixFlags)
|
||||
{
|
||||
_loggingEventHelper.Fix = newFixFlags;
|
||||
_fixFlags = newFixFlags;
|
||||
InitializeAppenders();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeAppenders()
|
||||
{
|
||||
foreach (var appender in Appenders)
|
||||
{
|
||||
SetAppenderFixFlags(appender);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetAppenderFixFlags(IAppender appender)
|
||||
{
|
||||
var bufferingAppender = appender as BufferingAppenderSkeleton;
|
||||
if (bufferingAppender != null)
|
||||
{
|
||||
bufferingAppender.Fix = Fix;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Appender Management
|
||||
|
||||
#region Forwarding
|
||||
|
||||
protected void ForwardInternalError(string message, Exception exception, Type thisType)
|
||||
{
|
||||
LogLog.Error(thisType, message, exception);
|
||||
var loggingEvent = _loggingEventHelper.CreateLoggingEvent(Level.Error, message, exception);
|
||||
ForwardLoggingEvent(loggingEvent, thisType);
|
||||
}
|
||||
|
||||
protected void ForwardLoggingEvent(LoggingEvent loggingEvent, Type thisType)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Append(loggingEvent);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
LogLog.Error(thisType, "Unable to forward logging event", exception);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Forwarding
|
||||
}
|
||||
}
|
||||
@@ -1,276 +1,276 @@
|
||||
using log4net.Core;
|
||||
using log4net.Util;
|
||||
using System;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Security.Principal;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using log4net.Appender;
|
||||
using log4net.Core;
|
||||
using log4net.Util;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Based on code by Chris Haines http://cjbhaines.wordpress.com/2012/02/13/asynchronous-log4net-appenders/
|
||||
/// <summary>
|
||||
/// Based on https://github.com/cjbhaines/Log4Net.Async
|
||||
/// which is based on code by Chris Haines http://cjbhaines.wordpress.com/2012/02/13/asynchronous-log4net-appenders/
|
||||
/// </summary>
|
||||
public class AsynchronousRollingFileAppender : RollingFileAppender
|
||||
{
|
||||
private readonly ManualResetEvent _manualResetEvent;
|
||||
private int _bufferOverflowCounter;
|
||||
private bool _forceStop;
|
||||
private bool _hasFinished;
|
||||
private DateTime _lastLoggedBufferOverflow;
|
||||
private bool _logBufferOverflow;
|
||||
private RingBuffer<LoggingEvent> _pendingAppends;
|
||||
private int _queueSizeLimit = 1000;
|
||||
private bool _shuttingDown;
|
||||
private RingBuffer<LoggingEvent> pendingAppends;
|
||||
private readonly ManualResetEvent manualResetEvent;
|
||||
private bool shuttingDown;
|
||||
private bool hasFinished;
|
||||
private bool forceStop;
|
||||
private bool logBufferOverflow;
|
||||
private int bufferOverflowCounter;
|
||||
private DateTime lastLoggedBufferOverflow;
|
||||
private int queueSizeLimit = 1000;
|
||||
public int QueueSizeLimit
|
||||
{
|
||||
get
|
||||
{
|
||||
return queueSizeLimit;
|
||||
}
|
||||
set
|
||||
{
|
||||
queueSizeLimit = value;
|
||||
}
|
||||
}
|
||||
|
||||
public AsynchronousRollingFileAppender()
|
||||
{
|
||||
_manualResetEvent = new ManualResetEvent(false);
|
||||
}
|
||||
public AsynchronousRollingFileAppender()
|
||||
{
|
||||
manualResetEvent = new ManualResetEvent(false);
|
||||
}
|
||||
|
||||
public int QueueSizeLimit
|
||||
{
|
||||
get { return _queueSizeLimit; }
|
||||
set { _queueSizeLimit = value; }
|
||||
}
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
pendingAppends = new RingBuffer<LoggingEvent>(QueueSizeLimit);
|
||||
pendingAppends.BufferOverflow += OnBufferOverflow;
|
||||
StartAppendTask();
|
||||
}
|
||||
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
_pendingAppends = new RingBuffer<LoggingEvent>(QueueSizeLimit);
|
||||
_pendingAppends.BufferOverflow += OnBufferOverflow;
|
||||
StartAppendTask();
|
||||
}
|
||||
protected override void Append(LoggingEvent[] loggingEvents)
|
||||
{
|
||||
Array.ForEach(loggingEvents, Append);
|
||||
}
|
||||
|
||||
protected override void Append(LoggingEvent[] loggingEvents)
|
||||
{
|
||||
Array.ForEach(loggingEvents, Append);
|
||||
}
|
||||
protected override void Append(LoggingEvent loggingEvent)
|
||||
{
|
||||
if (FilterEvent(loggingEvent))
|
||||
{
|
||||
pendingAppends.Enqueue(loggingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Append(LoggingEvent loggingEvent)
|
||||
{
|
||||
if (FilterEvent(loggingEvent))
|
||||
{
|
||||
_pendingAppends.Enqueue(loggingEvent);
|
||||
}
|
||||
}
|
||||
protected override void OnClose()
|
||||
{
|
||||
shuttingDown = true;
|
||||
manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
_shuttingDown = true;
|
||||
_manualResetEvent.WaitOne(TimeSpan.FromSeconds(5));
|
||||
if (!hasFinished)
|
||||
{
|
||||
forceStop = true;
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = Level.Error,
|
||||
Message = "Unable to clear out the AsyncRollingFileAppender buffer in the allotted time, forcing a shutdown",
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = "",
|
||||
UserName = WindowsIdentity.GetCurrent() != null ? WindowsIdentity.GetCurrent().Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo = new LocationInfo(this.GetType().Name, "OnClose", "AsyncRollingFileAppender.cs", "75"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (!_hasFinished)
|
||||
{
|
||||
_forceStop = true;
|
||||
var windowsIdentity = WindowsIdentity.GetCurrent();
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
var logEvent = new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = global::log4net.Core.Level.Error,
|
||||
Message =
|
||||
"Unable to clear out the AsynchronousRollingFileAppender buffer in the allotted time, forcing a shutdown",
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = "",
|
||||
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo =
|
||||
new LocationInfo(this.GetType().Name, "OnClose", "AsynchronousRollingFileAppender.cs", "59"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
});
|
||||
private void StartAppendTask()
|
||||
{
|
||||
if (!shuttingDown)
|
||||
{
|
||||
Task appendTask = new Task(AppendLoggingEvents, TaskCreationOptions.LongRunning);
|
||||
appendTask.LogErrors(LogAppenderError).ContinueWith(x => StartAppendTask()).LogErrors(LogAppenderError);
|
||||
appendTask.Start();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.DateTimeStrategy != null)
|
||||
{
|
||||
base.Append(logEvent);
|
||||
}
|
||||
}
|
||||
private void LogAppenderError(string logMessage, Exception exception)
|
||||
{
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = Level.Error,
|
||||
Message = "Appender exception: " + logMessage,
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = exception.ToString(),
|
||||
UserName = WindowsIdentity.GetCurrent() != null ? WindowsIdentity.GetCurrent().Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo = new LocationInfo(this.GetType().Name, "LogAppenderError", "AsyncRollingFileAppender.cs", "152"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
}));
|
||||
}
|
||||
|
||||
base.OnClose();
|
||||
}
|
||||
private void AppendLoggingEvents()
|
||||
{
|
||||
LoggingEvent loggingEventToAppend;
|
||||
while (!shuttingDown)
|
||||
{
|
||||
if (logBufferOverflow)
|
||||
{
|
||||
LogBufferOverflowError();
|
||||
logBufferOverflow = false;
|
||||
bufferOverflowCounter = 0;
|
||||
lastLoggedBufferOverflow = DateTime.UtcNow;
|
||||
}
|
||||
|
||||
private void StartAppendTask()
|
||||
{
|
||||
if (!_shuttingDown)
|
||||
{
|
||||
Task appendTask = new Task(AppendLoggingEvents, TaskCreationOptions.LongRunning);
|
||||
appendTask.LogErrors(LogAppenderError).ContinueWith(x => StartAppendTask()).LogErrors(LogAppenderError);
|
||||
appendTask.Start();
|
||||
}
|
||||
}
|
||||
while (!pendingAppends.TryDequeue(out loggingEventToAppend))
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
if (shuttingDown)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (loggingEventToAppend == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
private void LogAppenderError(string logMessage, Exception exception)
|
||||
{
|
||||
var windowsIdentity = WindowsIdentity.GetCurrent();
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = Level.Error,
|
||||
Message = "Appender exception: " + logMessage,
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = exception.ToString(),
|
||||
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo =
|
||||
new LocationInfo(this.GetType().Name,
|
||||
"LogAppenderError",
|
||||
"AsynchronousRollingFileAppender.cs",
|
||||
"100"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
}));
|
||||
}
|
||||
try
|
||||
{
|
||||
base.Append(loggingEventToAppend);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private void AppendLoggingEvents()
|
||||
{
|
||||
LoggingEvent loggingEventToAppend;
|
||||
while (!_shuttingDown)
|
||||
{
|
||||
if (_logBufferOverflow)
|
||||
{
|
||||
LogBufferOverflowError();
|
||||
_logBufferOverflow = false;
|
||||
_bufferOverflowCounter = 0;
|
||||
_lastLoggedBufferOverflow = DateTime.UtcNow;
|
||||
}
|
||||
while (pendingAppends.TryDequeue(out loggingEventToAppend) && !forceStop)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Append(loggingEventToAppend);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
hasFinished = true;
|
||||
manualResetEvent.Set();
|
||||
}
|
||||
|
||||
while (!_pendingAppends.TryDequeue(out loggingEventToAppend))
|
||||
{
|
||||
Thread.Sleep(10);
|
||||
if (_shuttingDown)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (loggingEventToAppend == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
private void LogBufferOverflowError()
|
||||
{
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = Level.Error,
|
||||
Message = string.Format("Buffer overflow. {0} logging events have been lost in the last 30 seconds. [QueueSizeLimit: {1}]", bufferOverflowCounter, QueueSizeLimit),
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = "",
|
||||
UserName = WindowsIdentity.GetCurrent() != null ? WindowsIdentity.GetCurrent().Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo = new LocationInfo(this.GetType().Name, "LogBufferOverflowError", "AsyncRollingFileAppender.cs", "152"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
}));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
base.Append(loggingEventToAppend);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
private void OnBufferOverflow(object sender, EventArgs eventArgs)
|
||||
{
|
||||
bufferOverflowCounter++;
|
||||
if (logBufferOverflow == false)
|
||||
{
|
||||
if (lastLoggedBufferOverflow < DateTime.UtcNow.AddSeconds(-30))
|
||||
{
|
||||
logBufferOverflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (_pendingAppends.TryDequeue(out loggingEventToAppend) && !_forceStop)
|
||||
{
|
||||
try
|
||||
{
|
||||
base.Append(loggingEventToAppend);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
_hasFinished = true;
|
||||
_manualResetEvent.Set();
|
||||
}
|
||||
internal interface IQueue<T>
|
||||
{
|
||||
void Enqueue(T item);
|
||||
bool TryDequeue(out T ret);
|
||||
}
|
||||
|
||||
private void LogBufferOverflowError()
|
||||
{
|
||||
var windowsIdentity = WindowsIdentity.GetCurrent();
|
||||
base.Append(new LoggingEvent(new LoggingEventData
|
||||
{
|
||||
Level = Level.Error,
|
||||
Message =
|
||||
string.Format(
|
||||
"Buffer overflow. {0} logging events have been lost in the last 30 seconds. [QueueSizeLimit: {1}]",
|
||||
_bufferOverflowCounter,
|
||||
QueueSizeLimit),
|
||||
TimeStamp = DateTime.UtcNow,
|
||||
Identity = "",
|
||||
ExceptionString = "",
|
||||
UserName = windowsIdentity != null ? windowsIdentity.Name : "",
|
||||
Domain = AppDomain.CurrentDomain.FriendlyName,
|
||||
ThreadName = Thread.CurrentThread.ManagedThreadId.ToString(),
|
||||
LocationInfo =
|
||||
new LocationInfo(this.GetType().Name,
|
||||
"LogBufferOverflowError",
|
||||
"AsynchronousRollingFileAppender.cs",
|
||||
"172"),
|
||||
LoggerName = this.GetType().FullName,
|
||||
Properties = new PropertiesDictionary(),
|
||||
}));
|
||||
}
|
||||
internal class RingBuffer<T> : IQueue<T>
|
||||
{
|
||||
private readonly object lockObject = new object();
|
||||
private readonly T[] buffer;
|
||||
private readonly int size;
|
||||
private int readIndex = 0;
|
||||
private int writeIndex = 0;
|
||||
private bool bufferFull = false;
|
||||
|
||||
private void OnBufferOverflow(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_bufferOverflowCounter++;
|
||||
if (_logBufferOverflow == false)
|
||||
{
|
||||
if (_lastLoggedBufferOverflow < DateTime.UtcNow.AddSeconds(-30))
|
||||
{
|
||||
_logBufferOverflow = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public int Size { get { return size; } }
|
||||
|
||||
private class RingBuffer<T>
|
||||
{
|
||||
private readonly object _lockObject = new object();
|
||||
private readonly T[] _buffer;
|
||||
private readonly int _size;
|
||||
private int _readIndex = 0;
|
||||
private int _writeIndex = 0;
|
||||
private bool _bufferFull = false;
|
||||
public event Action<object, EventArgs> BufferOverflow;
|
||||
|
||||
public event Action<object, EventArgs> BufferOverflow;
|
||||
public RingBuffer(int size)
|
||||
{
|
||||
this.size = size;
|
||||
buffer = new T[size];
|
||||
}
|
||||
|
||||
public RingBuffer(int size)
|
||||
{
|
||||
this._size = size;
|
||||
_buffer = new T[size];
|
||||
}
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
var bufferWasFull = false;
|
||||
lock (lockObject)
|
||||
{
|
||||
buffer[writeIndex] = item;
|
||||
writeIndex = (++writeIndex) % size;
|
||||
if (bufferFull)
|
||||
{
|
||||
bufferWasFull = true;
|
||||
readIndex = writeIndex;
|
||||
}
|
||||
else if (writeIndex == readIndex)
|
||||
{
|
||||
bufferFull = true;
|
||||
}
|
||||
}
|
||||
|
||||
public void Enqueue(T item)
|
||||
{
|
||||
lock (_lockObject)
|
||||
{
|
||||
_buffer[_writeIndex] = item;
|
||||
_writeIndex = (++_writeIndex) % _size;
|
||||
if (_bufferFull)
|
||||
{
|
||||
if (BufferOverflow != null)
|
||||
{
|
||||
BufferOverflow(this, EventArgs.Empty);
|
||||
}
|
||||
_readIndex = _writeIndex;
|
||||
}
|
||||
else if (_writeIndex == _readIndex)
|
||||
{
|
||||
_bufferFull = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bufferWasFull)
|
||||
{
|
||||
if (BufferOverflow != null)
|
||||
{
|
||||
BufferOverflow(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryDequeue(out T ret)
|
||||
{
|
||||
if (_readIndex == _writeIndex && !_bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
lock (_lockObject)
|
||||
{
|
||||
if (_readIndex == _writeIndex && !_bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
public bool TryDequeue(out T ret)
|
||||
{
|
||||
if (readIndex == writeIndex && !bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
lock (lockObject)
|
||||
{
|
||||
if (readIndex == writeIndex && !bufferFull)
|
||||
{
|
||||
ret = default(T);
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = _buffer[_readIndex];
|
||||
_readIndex = (++_readIndex) % _size;
|
||||
_bufferFull = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = buffer[readIndex];
|
||||
buffer[readIndex] = default(T);
|
||||
readIndex = (++readIndex) % size;
|
||||
bufferFull = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
internal class DebugDiagnosticsLogger : ILogger
|
||||
{
|
||||
public void Error(Type callingType, string message, Exception exception)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(message + Environment.NewLine + exception, callingType.ToString());
|
||||
}
|
||||
|
||||
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(message, formatItems.Select(x => x()).ToArray()), callingType.ToString());
|
||||
}
|
||||
|
||||
public void WarnWithException(Type callingType, string message, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(message + Environment.NewLine + e, formatItems.Select(x => x()).ToArray()), callingType.ToString());
|
||||
}
|
||||
|
||||
public void Info(Type callingType, Func<string> generateMessage)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(generateMessage(), callingType.ToString());
|
||||
}
|
||||
|
||||
public void Info(Type type, string generateMessageFormat, params Func<object>[] formatItems)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray()), type.ToString());
|
||||
}
|
||||
|
||||
public void Debug(Type callingType, Func<string> generateMessage)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(generateMessage(), callingType.ToString());
|
||||
}
|
||||
|
||||
public void Debug(Type type, string generateMessageFormat, params Func<object>[] formatItems)
|
||||
{
|
||||
System.Diagnostics.Debug.WriteLine(string.Format(generateMessageFormat, formatItems.Select(x => x()).ToArray()), type.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface for logging service.
|
||||
/// </summary>
|
||||
public interface ILogger
|
||||
{
|
||||
void Error(Type callingType, string message, Exception exception);
|
||||
|
||||
void Warn(Type callingType, string message, params Func<object>[] formatItems);
|
||||
|
||||
void WarnWithException(Type callingType, string message, Exception e, params Func<object>[] formatItems);
|
||||
|
||||
void Info(Type callingType, Func<string> generateMessage);
|
||||
|
||||
void Info(Type type, string generateMessageFormat, params Func<object>[] formatItems);
|
||||
|
||||
void Debug(Type callingType, Func<string> generateMessage);
|
||||
|
||||
void Debug(Type type, string generateMessageFormat, params Func<object>[] formatItems);
|
||||
}
|
||||
}
|
||||
@@ -6,43 +6,14 @@ using log4net;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
///<summary>
|
||||
/// Used for logging
|
||||
///<summary>
|
||||
/// Used for logging, ILogger should be used instead but this is available for static access to logging
|
||||
///</summary>
|
||||
/// <remarks>
|
||||
/// this wraps ILogger
|
||||
/// </remarks>
|
||||
public static class LogHelper
|
||||
{
|
||||
///<summary>
|
||||
/// Returns a logger for the type specified
|
||||
///</summary>
|
||||
///<typeparam name="T"></typeparam>
|
||||
///<returns></returns>
|
||||
internal static ILog LoggerFor<T>()
|
||||
{
|
||||
return LogManager.GetLogger(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a logger for the object's type
|
||||
/// </summary>
|
||||
/// <param name="getTypeFromInstance"></param>
|
||||
/// <returns></returns>
|
||||
internal static ILog LoggerFor(object getTypeFromInstance)
|
||||
{
|
||||
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
|
||||
|
||||
return LogManager.GetLogger(getTypeFromInstance.GetType());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Useful if the logger itself is running on another thread
|
||||
/// </summary>
|
||||
/// <param name="generateMessageFormat"></param>
|
||||
/// <returns></returns>
|
||||
private static string PrefixThreadId(string generateMessageFormat)
|
||||
{
|
||||
return "[T" + Thread.CurrentThread.ManagedThreadId + "/D" + AppDomain.CurrentDomain.Id + "] " + generateMessageFormat;
|
||||
}
|
||||
|
||||
#region Error
|
||||
/// <summary>
|
||||
/// Adds an error log
|
||||
@@ -52,14 +23,14 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="exception"></param>
|
||||
public static void Error<T>(string message, Exception exception)
|
||||
{
|
||||
Error(typeof (T), message, exception);
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Error<T>(message, exception);
|
||||
}
|
||||
|
||||
public static void Error(Type callingType, string message, Exception exception)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.Error(PrefixThreadId(message), exception);
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Error(callingType, message, exception);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -68,11 +39,11 @@ namespace Umbraco.Core.Logging
|
||||
|
||||
public static void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsWarnEnabled) return;
|
||||
logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray());
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Warn(callingType, message, formatItems);
|
||||
}
|
||||
|
||||
[Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")]
|
||||
public static void Warn(Type callingType, string message, bool showHttpTrace, params Func<object>[] formatItems)
|
||||
{
|
||||
Mandate.ParameterNotNull(callingType, "callingType");
|
||||
@@ -81,11 +52,10 @@ namespace Umbraco.Core.Logging
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsWarnEnabled) return;
|
||||
logger.WarnFormat(PrefixThreadId(message), formatItems.Select(x => x.Invoke()).ToArray());
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Warn(callingType, message, formatItems);
|
||||
|
||||
}
|
||||
|
||||
@@ -94,6 +64,7 @@ namespace Umbraco.Core.Logging
|
||||
WarnWithException(callingType, message, false, e, formatItems);
|
||||
}
|
||||
|
||||
[Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")]
|
||||
public static void WarnWithException(Type callingType, string message, bool showHttpTrace, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
Mandate.ParameterNotNull(e, "e");
|
||||
@@ -108,10 +79,8 @@ namespace Umbraco.Core.Logging
|
||||
e);
|
||||
}
|
||||
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsWarnEnabled) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.WarnFormat(PrefixThreadId(message) + ". Exception: " + e, executedParams);
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.WarnWithException(callingType, message, e, formatItems);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -125,6 +94,7 @@ namespace Umbraco.Core.Logging
|
||||
Warn(typeof(T), message, formatItems);
|
||||
}
|
||||
|
||||
[Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")]
|
||||
public static void Warn<T>(string message, bool showHttpTrace, params Func<object>[] formatItems)
|
||||
{
|
||||
Warn(typeof(T), message, showHttpTrace, formatItems);
|
||||
@@ -134,6 +104,8 @@ namespace Umbraco.Core.Logging
|
||||
{
|
||||
WarnWithException(typeof(T), message, e, formatItems);
|
||||
}
|
||||
|
||||
[Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")]
|
||||
public static void WarnWithException<T>(string message, bool showHttpTrace, Exception e, params Func<object>[] formatItems)
|
||||
{
|
||||
WarnWithException(typeof(T), message, showHttpTrace, e, formatItems);
|
||||
@@ -160,9 +132,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="generateMessage"></param>
|
||||
public static void Info(Type callingType, Func<string> generateMessage)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsInfoEnabled) return;
|
||||
logger.Info(PrefixThreadId(generateMessage.Invoke()));
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Info(callingType, generateMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -173,10 +144,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="formatItems">The format items.</param>
|
||||
public static void Info(Type type, string generateMessageFormat, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(type);
|
||||
if (logger == null || !logger.IsInfoEnabled) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.InfoFormat(PrefixThreadId(generateMessageFormat), executedParams);
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Info(type, generateMessageFormat, formatItems);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -211,9 +180,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="generateMessage"></param>
|
||||
public static void Debug(Type callingType, Func<string> generateMessage)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || !logger.IsDebugEnabled) return;
|
||||
logger.Debug(PrefixThreadId(generateMessage.Invoke()));
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Debug(callingType, generateMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -224,10 +192,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="formatItems">The format items.</param>
|
||||
public static void Debug(Type type, string generateMessageFormat, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(type);
|
||||
if (logger == null || !logger.IsDebugEnabled) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.DebugFormat(PrefixThreadId(generateMessageFormat), executedParams);
|
||||
if (LoggerResolver.HasCurrent == false || LoggerResolver.Current.HasValue == false) return;
|
||||
LoggerResolver.Current.Logger.Debug(type, generateMessageFormat, formatItems);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -250,6 +216,7 @@ namespace Umbraco.Core.Logging
|
||||
/// <param name="generateMessageFormat"></param>
|
||||
/// <param name="showHttpTrace"></param>
|
||||
/// <param name="formatItems"></param>
|
||||
[Obsolete("Warnings with http trace should not be used. This method will be removed in future versions")]
|
||||
public static void Debug<T>(string generateMessageFormat, bool showHttpTrace, params Func<object>[] formatItems)
|
||||
{
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user