You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by dj...@apache.org on 2016/08/17 14:21:08 UTC

svn commit: r1756639 [1/5] - in /jackrabbit/oak/branches/1.2: ./ oak-commons/ oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/ oak-core/src/main/java/org/apache/jackrabbit...

Author: dj
Date: Wed Aug 17 14:21:07 2016
New Revision: 1756639

URL: http://svn.apache.org/viewvc?rev=1756639&view=rev
Log:
OAK-4679 : Backport OAK-4119, OAK-4101, OAK-4087 and OAK-4344
- backported OAK-4119
  - depends on OAK-4003
  - depends on OAK-3721
  - depends on OAK-2742
  - depends on OAK-3728
  - depends on OAK-3170
    - depends on Jackrabbit >= 2.11.0 
    - depends on OAK-2994
    - depends on OAK-2690

Added:
    jackrabbit/oak/branches/1.2/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/QueryUtils.java
      - copied unchanged from r1738138, jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/QueryUtils.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java
      - copied unchanged from r1675089, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AbstractGroupPrincipal.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/SystemUserPrincipalImpl.java
      - copied unchanged from r1675089, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/SystemUserPrincipalImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java
      - copied unchanged from r1675089, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProvider.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractGroupAction.java
      - copied unchanged from r1735564, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/AbstractGroupAction.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/GroupAction.java
      - copied unchanged from r1735564, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/GroupAction.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractAddMembersByIdTest.java
      - copied, changed from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractAddMembersByIdTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractRemoveMembersByIdTest.java
      - copied unchanged from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AbstractRemoveMembersByIdTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdAbortTest.java
      - copied unchanged from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdAbortTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdBestEffortTest.java
      - copied, changed from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdBestEffortTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdIgnoreTest.java
      - copied unchanged from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AddMembersByIdIgnoreTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdAbortTest.java
      - copied unchanged from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdAbortTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdBestEffortTest.java
      - copied, changed from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdBestEffortTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdIgnoreTest.java
      - copied unchanged from r1694049, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/RemoveMembersByIdIgnoreTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProviderTest.java
      - copied unchanged from r1675089, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserPrincipalProviderTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/AbstractPrincipalProviderTest.java
      - copied unchanged from r1675089, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/principal/AbstractPrincipalProviderTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/user/action/GroupActionBestEffortTest.java
      - copied, changed from r1735564, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/user/action/GroupActionBestEffortTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/user/action/GroupActionTest.java
      - copied, changed from r1735564, jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/user/action/GroupActionTest.java
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user/groupaction.md
      - copied unchanged from r1735564, jackrabbit/oak/trunk/oak-doc/src/site/markdown/security/user/groupaction.md
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithActionsBestEffortTest.java
      - copied, changed from r1735564, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithActionsBestEffortTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithActionsTest.java
      - copied, changed from r1735564, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithActionsTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithPoliciesTest.java
      - copied unchanged from r1672469, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithPoliciesTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithoutAdminTest.java
      - copied unchanged from r1672469, jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportWithoutAdminTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/GetGroupPrincipalsTest.java
      - copied unchanged from r1675089, jackrabbit/oak/trunk/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/GetGroupPrincipalsTest.java
Modified:
    jackrabbit/oak/branches/1.2/   (props changed)
    jackrabbit/oak/branches/1.2/oak-commons/pom.xml
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyBuilder.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalConfigurationImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipWriter.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/SystemUserImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserInitializer.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserValidator.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/autosave/GroupImpl.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/query/QueryUtil.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/AuthorizableType.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/UserConfiguration.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/action/package-info.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/UserUtil.java
    jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/security/user/util/package-info.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/index/AsyncIndexUpdateTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImplTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/MembershipProviderTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserInitializerTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserValidatorTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/autosave/AutoSaveEnabledManagerTest.java
    jackrabbit/oak/branches/1.2/oak-core/src/test/java/org/apache/jackrabbit/oak/spi/security/user/action/PasswordValidationActionTest.java
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user.md
    jackrabbit/oak/branches/1.2/oak-doc/src/site/markdown/security/user/membership.md
    jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/GroupDelegator.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionImpl.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/authorization/AbstractEvaluationTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/AbstractImportTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportAbortTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportBestEffortTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportIgnoreTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupImportTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/GroupTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/NestedGroupTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/SystemUserImportTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportAbortTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportBestEffortTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportFromJackrabbit.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportIgnoreTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportPwExpiryTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportTest.java
    jackrabbit/oak/branches/1.2/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/security/user/UserImportWithActionsTest.java
    jackrabbit/oak/branches/1.2/oak-parent/pom.xml
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/AbstractLoginTest.java
    jackrabbit/oak/branches/1.2/oak-run/src/main/java/org/apache/jackrabbit/oak/benchmark/BenchmarkRunner.java

Propchange: jackrabbit/oak/branches/1.2/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Aug 17 14:21:07 2016
@@ -1,4 +1,4 @@
 /jackrabbit/oak/branches/1.0:1665962
 /jackrabbit/oak/branches/1.4:1745750,1747354,1750078,1750512
-/jackrabbit/oak/trunk:1672350,1672468,1672537,1672603,1672611,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673713,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678023,1678095-1678096,1678124,1678171,1678173,1678202,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680170,1680172,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1681921,1681955,1682042,1682218,1682235,1682437,1682488,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376,1684442,1684561
 ,1684570,1684601,1684618,1684669,1684820,1684868,1684894,1685023,1685075,1685370,1685541,1685552,1685589-1685590,1685840,1685964,1685977,1685989,1685999,1686003,1686023,1686032,1686097,1686162,1686229,1686234,1686253,1686414,1686772,1686780,1686790,1686854,1686857,1686971,1687053-1687055,1687175,1687196,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688179,1688349,1688421,1688436,1688453,1688616,1688622,1688634,1688636,1688817,1689003-1689004,1689008,1689577,1689581,1689623,1689810,1689828,1689831,1689833,1689903,1690017,1690043,1690047,1690057,1690247,1690249,1690634-1690637,1690650,1690657,1690669,1690672,1690674,1690885,1690941,1691139,1691151,1691159,1691167,1691183,1691188,1691201,1691210,1691217-1691218,1691280,1691307,1691331-1691333,1691345,1691384-1691385,1691394,1691401,1691498,1691509,1692133-1692134,1692156,1692250,1692272,1692274,1692363,1692382,1692393,1692478,1692955,1693002,1693030,1693050,1693209,1693401,1693421,1693525-1693526,1694
 007,1694393-1694394,1694651,1694653-1694654,1695032,1695050,1695122,1695280,1695299,1695420,1695457,1695482,1695492,1695507,1695521,1695540,1695571,1695829-1695830,1695905,1696190,1696194,1696242,1696285,1696375,1696522,1696578,1696759,1696916,1697363,1697373,1697383,1697410,1697582,1697589,1697616,1697672,1697896,1698096,1698144,1700191,1700231,1700397,1700403,1700506,1700571,1700709,1700718,1700720,1700727,1700749,1700769,1700775,1701065,1701613,1701619,1701733,1701743,1701750,1701768,1701806,1701810,1701814,1701907,1701948,1701955,1701959,1701965,1701986,1702014,1702022,1702045,1702051,1702241,1702272,1702371,1702387,1702405,1702423,1702426,1702428,1702860,1702866,1702942,1702960,1703212,1703382,1703395,1703411,1703428,1703430,1703568,1703592,1703758,1703858,1703878,1704256,1704282,1704285,1704457,1704479,1704490,1704614,1704629,1704636,1704655,1704670,1704886,1705005,1705027,1705043,1705055,1705250,1705268,1705273,1705323,1705677,1705701,1705871,1705992,1705998,1706009,1706037,1
 706059,1706212,1706218,1706270,1706764,1706772,1707049,1707189,1707191,1707331,1707435,1707509,1707753,1708049,1708105,1708307,1708315,1708401,1708546,1708592,1708766,1709012,1709852,1709978,1710013,1710031,1710049,1710205,1710242,1710559,1710575,1710590,1710614,1710637,1710789,1710800,1710811,1710816,1710972,1711248,1711282,1711296,1711405,1711498,1711654,1712018,1712042,1712319,1712490,1712531,1712730,1712785,1712963,1713008,1713439,1713461,1713580,1713586,1713599-1713600,1713626,1713698,1713803,1713809,1714034,1714061,1714084,1714170,1714213,1714229,1714238,1714519-1714520,1714543-1714544,1714730,1714739,1714779,1714956,1714961,1715010,1715092,1715191,1715346,1715716,1715767,1715771,1715888,1715898,1716100,1716178,1716426,1716576,1716588-1716589,1716596,1716616,1716703,1716712,1716815,1716823,1716830,1716883,1717203,1717277,1717393-1717394,1717410,1717462,1717632,1717768-1717769,1717784,1717789,1717988,1718528,1718533,1718547-1718548,1718626,1718646,1718772,1718801-1718802,171889
 5,1719111,1719288,1719869,1720306,1720335,1720350,1720354,1720500,1721160,1721172,1721337,1722141,1722832,1723227,1723239,1723241,1723251,1723254,1723333,1723347,1723350,1723565,1723584,1723713,1723731,1724026,1724057,1724186,1724210,1724401,1724628,1724631,1725216,1725477,1725515,1725555,1725895,1725899,1725935,1725941,1725960,1726232,1726237,1726570,1726579,1726585-1726586,1726621,1726795,1726797,1726809,1726812,1726981,1726993,1727026,1727254,1727331,1727350,1727358,1727429,1727476,1727483,1727508,1727515-1727518,1727813,1727816,1727831-1727832,1727841,1727893,1727895,1727912-1727913,1727923,1727991,1728037,1728041,1728070,1728114,1728281,1728443,1728525,1728642,1729200,1729505,1729599,1729957,1729979,1730216,1730527,1730581,1730629,1730801,1731627,1731647-1731648,1731789,1731797,1732131,1732268,1732278,1732330,1732647-1732648,1732864,1733615,1733929,1734230,1734254,1735052,1735267,1735405,1735484,1735588,1736176,1737309-1737310,1737334,1737349,1738833,1738950,1738957,1739894,174
 0116,1740626,1740971,1741032,1741339,1741343,1742520,1742888,1742916,1743097,1743172,1743343,1744265,1744959,1745038,1745197,1746117,1746696,1746981,1747341-1747342,1747492,1748505,1748553,1748722,1748870,1749350,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1752198,1752202,1752273-1752274,1752438,1752508,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755366,1756520,1756580
+/jackrabbit/oak/trunk:1672350,1672468-1672469,1672537,1672603,1672611,1672642,1672644,1672834-1672835,1673351,1673410,1673414-1673415,1673436,1673644,1673662-1673664,1673669,1673695,1673713,1673738,1673787,1673791,1674046,1674065,1674075,1674107,1674228,1674780,1674880,1675054-1675055,1675089,1675319,1675332,1675354,1675357,1675382,1675555,1675566,1675593,1676198,1676237,1676407,1676458,1676539,1676670,1676693,1676703,1676725,1677579,1677581,1677609,1677611,1677774,1677788,1677797,1677804,1677806,1677939,1677991,1678023,1678095-1678096,1678124,1678171,1678173,1678202,1678211,1678323,1678758,1678938,1678954,1679144,1679165,1679191,1679232,1679235,1679503,1679958,1679961,1680170,1680172,1680182,1680222,1680232,1680236,1680461,1680633,1680643,1680747,1680805-1680806,1680903,1681282,1681767,1681918,1681921,1681955,1682042,1682218,1682235,1682437,1682488,1682494,1682555,1682855,1682904,1683059,1683089,1683213,1683249,1683259,1683278,1683323,1683687,1683700,1684174-1684175,1684186,1684376
 ,1684442,1684561,1684570,1684601,1684618,1684669,1684820,1684868,1684894,1685023,1685075,1685370,1685541,1685552,1685589-1685590,1685839-1685840,1685964,1685977,1685989,1685999,1686003,1686023,1686032,1686097,1686162,1686229,1686234,1686253,1686414,1686772,1686780,1686790,1686854,1686857,1686971,1687053-1687055,1687175,1687196,1687198,1687220,1687239-1687240,1687301,1687441,1687553,1688089-1688090,1688172,1688179,1688349,1688421,1688436,1688453,1688616,1688622,1688634,1688636,1688817,1689003-1689004,1689008,1689577,1689581,1689623,1689810,1689828,1689831,1689833,1689903,1690017,1690043,1690047,1690057,1690247,1690249,1690634-1690637,1690650,1690657,1690669,1690672,1690674,1690885,1690941,1691139,1691151,1691159,1691167,1691183,1691188,1691201,1691210,1691217-1691218,1691280,1691307,1691331-1691333,1691345,1691384-1691385,1691394,1691401,1691498,1691509,1692133-1692134,1692156,1692250,1692272,1692274,1692363,1692382,1692393,1692478,1692955,1693002,1693030,1693050,1693209,1693401,1693
 421,1693525-1693526,1694007,1694049,1694393-1694394,1694651,1694653-1694654,1695032,1695050,1695122,1695280,1695299,1695420,1695457,1695482,1695492,1695507,1695521,1695540,1695571,1695829-1695830,1695905,1696190,1696194,1696242,1696285,1696375,1696522,1696578,1696759,1696916,1697363,1697373,1697383,1697410,1697582,1697589,1697616,1697672,1697896,1698096,1698144,1700191,1700231,1700397,1700403,1700506,1700571,1700709,1700718,1700720,1700727,1700749,1700769,1700775,1701065,1701613,1701619,1701733,1701743,1701750,1701768,1701806,1701810,1701814,1701907,1701948,1701955,1701959,1701965,1701986,1702014,1702022,1702045,1702051,1702241,1702272,1702371,1702387,1702405,1702423,1702426,1702428,1702860,1702866,1702942,1702960,1703212,1703382,1703395,1703411,1703428,1703430,1703568,1703592,1703758,1703858,1703878,1704256,1704282,1704285,1704457,1704479,1704490,1704614,1704629,1704636,1704655,1704670,1704886,1705005,1705027,1705043,1705055,1705250,1705268,1705273,1705323,1705677,1705701,1705871,1
 705992,1705998,1706009,1706037,1706059,1706212,1706218,1706270,1706764,1706772,1707049,1707189,1707191,1707331,1707435,1707509,1707753,1708049,1708105,1708307,1708315,1708401,1708546,1708592,1708766,1709012,1709852,1709978,1710013,1710031,1710049,1710205,1710242,1710559,1710575,1710590,1710614,1710637,1710789,1710800,1710811,1710816,1710972,1711248,1711282,1711296,1711405,1711498,1711654,1712018,1712042,1712319,1712490,1712531,1712730,1712785,1712963,1713008,1713439,1713461,1713580,1713586,1713599-1713600,1713626,1713698,1713803,1713809,1714034,1714061,1714084,1714170,1714213,1714229,1714238,1714519-1714520,1714543-1714544,1714730,1714739,1714779,1714956,1714961,1715010,1715092,1715191,1715346,1715716,1715767,1715771,1715888,1715898,1716100,1716178,1716426,1716576,1716588-1716589,1716596,1716616,1716703,1716712,1716815,1716823,1716830,1716883,1717203,1717277,1717393-1717394,1717410,1717462,1717632,1717768-1717769,1717784,1717789,1717988,1718528,1718533,1718546-1718548,1718553,171862
 6,1718646,1718772,1718801-1718802,1718895,1719111,1719288,1719869,1720306,1720335,1720350,1720354,1720500,1721160,1721172,1721337,1722141,1722832,1723227,1723239,1723241,1723251,1723254,1723333,1723347,1723350,1723565,1723584,1723713,1723731,1724026,1724057,1724186,1724210,1724401,1724628,1724631,1725216,1725477,1725515,1725555,1725895,1725899,1725935,1725941,1725960,1726232,1726237,1726570,1726579,1726585-1726586,1726621,1726795,1726797,1726809,1726812,1726981,1726993,1727026,1727254,1727331,1727350,1727358,1727429,1727476,1727483,1727508,1727515-1727518,1727813,1727816,1727831-1727832,1727841,1727893,1727895,1727912-1727913,1727923,1727991,1728037,1728041,1728070,1728114,1728281,1728443,1728525,1728642,1729200,1729505,1729599,1729957,1729979,1730216,1730527,1730581,1730629,1730801,1731627,1731647-1731648,1731789,1731797,1732131,1732268,1732278,1732330,1732647-1732648,1732864,1733615,1733929,1734230,1734254,1735052,1735267,1735405,1735484,1735564,1735588,1736176,1737309-1737310,173
 7334,1737349,1738138,1738252,1738833,1738950,1738957,1739894,1740116,1740626,1740971,1741032,1741339,1741343,1742520,1742888,1742916,1743097,1743172,1743343,1744265,1744959,1745038,1745197,1746117,1746696,1746981,1747341-1747342,1747492,1748505,1748553,1748722,1748870,1749350,1749464,1749475,1749645,1749662,1749815,1749872,1749875,1749899,1750052,1750076-1750077,1750287,1750457,1750462,1750465,1750495,1750626,1750809,1750886,1751410,1751445-1751446,1751478,1751755,1752198,1752202,1752273-1752274,1752438,1752508,1752659,1752672,1753262,1753331-1753332,1753355,1753444,1754117,1754239,1755366,1756520,1756580
 /jackrabbit/trunk:1345480

Modified: jackrabbit/oak/branches/1.2/oak-commons/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-commons/pom.xml?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-commons/pom.xml (original)
+++ jackrabbit/oak/branches/1.2/oak-commons/pom.xml Wed Aug 17 14:21:07 2016
@@ -97,6 +97,11 @@
       <artifactId>commons-io</artifactId>
       <version>2.4</version>
     </dependency>
+    <dependency>
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-jcr-commons</artifactId>
+      <version>${jackrabbit.version}</version>
+    </dependency>
 
     <!-- Test dependencies -->
     <dependency>

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/IdentifierManager.java Wed Aug 17 14:21:07 2016
@@ -29,6 +29,8 @@ import javax.jcr.query.Query;
 
 import com.google.common.base.Charsets;
 import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Iterators;
 
 import org.apache.jackrabbit.JcrConstants;
@@ -41,6 +43,7 @@ import org.apache.jackrabbit.oak.api.Roo
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.commons.PathUtils;
+import org.apache.jackrabbit.oak.commons.QueryUtils;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.plugins.memory.StringPropertyState;
 import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager;
@@ -270,7 +273,7 @@ public class IdentifierManager {
                     }
 
                     // skip references from the version storage (OAK-1196)
-                    if (!rowPath.startsWith(VersionConstants.VERSION_STORE_PATH)) { 
+                    if (!rowPath.startsWith(VersionConstants.VERSION_STORE_PATH)) {
                         Tree tree = root.getTree(rowPath);
                         if (nodeTypeNames.length == 0 || containsNodeType(tree, nodeTypeNames)) {
                             if (propertyName == null) {
@@ -299,6 +302,58 @@ public class IdentifierManager {
         };
     }
 
+    /**
+     * Searches all reference properties to the specified {@code tree} that match
+     * the given {@code propertyName} and the specified, mandatory node type
+     * constraint ({@code ntName}). In contrast to {@link #getReferences} this
+     * method requires all parameters to be specified, which eases the handling
+     * of the result set and doesn't require the trees associated with the
+     * result set to be resolved.
+     *
+     * @param tree The tree for which references should be searched.
+     * @param propertyName The name of the reference properties.
+     * @param ntName The node type name to be used for the query.
+     * @param weak if {@code true} only weak references are returned. Otherwise on hard references are returned.
+     * @return A set of oak paths of those reference properties referring to the
+     *         specified {@code tree} and matching the constraints.
+     */
+    @Nonnull
+    public Iterable<String> getReferences(@Nonnull Tree tree, final @Nonnull String propertyName,
+                                          @Nonnull String ntName, boolean weak) {
+        if (!nodeTypeManager.isNodeType(tree, JcrConstants.MIX_REFERENCEABLE)) {
+            return Collections.emptySet(); // shortcut
+        }
+
+        final String uuid = getIdentifier(tree);
+        String reference = weak ? PropertyType.TYPENAME_WEAKREFERENCE : PropertyType.TYPENAME_REFERENCE;
+        Map<String, ? extends PropertyValue> bindings = Collections.singletonMap("uuid", PropertyValues.newString(uuid));
+
+        try {
+            String escapedPropName = QueryUtils.escapeForQuery(propertyName);
+            Result result = root.getQueryEngine().executeQuery(
+                    "SELECT * FROM [" + ntName + "] WHERE PROPERTY([" + escapedPropName + "], '" + reference + "') = $uuid" +
+                            QueryEngine.INTERNAL_SQL2_QUERY,
+                    Query.JCR_SQL2, Long.MAX_VALUE, 0, bindings, NO_MAPPINGS);
+
+            Iterable<String> resultPaths = Iterables.transform(result.getRows(), new Function<ResultRow, String>() {
+                @Override
+                public String apply(ResultRow row) {
+                    return PathUtils.concat(row.getPath(), propertyName);
+                }
+            });
+            return Iterables.filter(resultPaths, new Predicate<String>() {
+                        @Override
+                        public boolean apply(String path) {
+                            return !path.startsWith(VersionConstants.VERSION_STORE_PATH);
+                        }
+                    }
+            );
+        } catch (ParseException e) {
+            log.error("query failed", e);
+            return Collections.emptySet();
+        }
+    }
+
     @CheckForNull
     public String resolveUUID(String uuid) {
         return resolveUUID(StringPropertyState.stringProperty("", uuid));

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/index/IndexUtils.java Wed Aug 17 14:21:07 2016
@@ -103,13 +103,13 @@ public class IndexUtils {
      * @param propertyNames
      * @param declaringNodeTypeNames
      */
-    public static void createIndexDefinition(@Nonnull NodeUtil indexNode,
+    public static NodeUtil createIndexDefinition(@Nonnull NodeUtil indexNode,
                                              @Nonnull String indexDefName,
                                              boolean unique,
                                              @Nonnull String[] propertyNames,
                                              @Nullable String[] declaringNodeTypeNames) throws RepositoryException {
 
-        createIndexDefinition(indexNode, indexDefName, unique, propertyNames, declaringNodeTypeNames, PropertyIndexEditorProvider.TYPE);
+        return createIndexDefinition(indexNode, indexDefName, unique, propertyNames, declaringNodeTypeNames, PropertyIndexEditorProvider.TYPE);
     }
 
     /**
@@ -123,20 +123,21 @@ public class IndexUtils {
      * @param propertyIndexType
      * @throws RepositoryException
      */
-    public static void createIndexDefinition(@Nonnull NodeUtil indexNode, 
+    public static NodeUtil createIndexDefinition(@Nonnull NodeUtil indexNode, 
                                              @Nonnull String indexDefName, 
                                              boolean unique, 
                                              @Nonnull String[] propertyNames, 
                                              @Nullable String[] declaringNodeTypeNames, 
                                              @Nonnull String propertyIndexType) throws RepositoryException {
-        createIndexDefinition(indexNode, indexDefName, unique, propertyNames,
+        return createIndexDefinition(indexNode, indexDefName, unique, propertyNames,
             declaringNodeTypeNames, propertyIndexType, null);
     }
 
     public static void createReferenceIndex(@Nonnull NodeBuilder index) {
         index.child(NodeReferenceConstants.NAME)
                 .setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME)
-                .setProperty(TYPE_PROPERTY_NAME, NodeReferenceConstants.TYPE);
+                .setProperty(TYPE_PROPERTY_NAME, NodeReferenceConstants.TYPE)
+                .setProperty("info", "Oak index for reference lookup.");
     }
 
     public static boolean isIndexNodeType(NodeState state) {
@@ -167,7 +168,7 @@ public class IndexUtils {
      * @param properties any additional property to be added to the index definition.
      * @throws RepositoryException
      */
-    public static void createIndexDefinition(@Nonnull NodeUtil indexNode, 
+    public static NodeUtil createIndexDefinition(@Nonnull NodeUtil indexNode, 
                                              @Nonnull String indexDefName, 
                                              boolean unique, 
                                              @Nonnull String[] propertyNames, 
@@ -190,6 +191,7 @@ public class IndexUtils {
                 entry.setString(k, properties.get(k));
             }
         }
+        return entry;
     }
 
     /**
@@ -205,7 +207,7 @@ public class IndexUtils {
      * @param properties                any additional property to be added to the index definition.
      * @throws RepositoryException
      */
-    public static void createIndexDefinition(@Nonnull NodeBuilder indexNode, 
+    public static NodeBuilder createIndexDefinition(@Nonnull NodeBuilder indexNode, 
                                              @Nonnull String indexDefName, 
                                              boolean unique, 
                                              @Nonnull Iterable<String> propertyNames, 
@@ -231,5 +233,6 @@ public class IndexUtils {
                 entry.setProperty(k, properties.get(k));
             }
         }
+        return entry;
     }
 }

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyBuilder.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyBuilder.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/memory/PropertyBuilder.java Wed Aug 17 14:21:07 2016
@@ -25,6 +25,7 @@ import java.util.List;
 import javax.annotation.Nonnull;
 import javax.jcr.PropertyType;
 
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.PropertyState;
@@ -247,6 +248,12 @@ public class PropertyBuilder<T> {
         return this;
     }
 
+    @Nonnull
+    public PropertyBuilder<T> addValues(Iterable<T> values) {
+        Iterables.addAll(this.values, values);
+        return this;
+    }
+
     @Nonnull
     public PropertyBuilder<T> setValue(T value, int index) {
         values.set(index, value);

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java Wed Aug 17 14:21:07 2016
@@ -93,17 +93,25 @@ public class InitialContent implements R
         if (!builder.hasChildNode(IndexConstants.INDEX_DEFINITIONS_NAME)) {
             NodeBuilder index = IndexUtils.getOrCreateOakIndex(builder);
 
-            IndexUtils.createIndexDefinition(index, "uuid", true, true,
+            NodeBuilder uuid = IndexUtils.createIndexDefinition(index, "uuid", true, true,
                     ImmutableList.<String>of(JCR_UUID), null);
-            IndexUtils.createIndexDefinition(index, "nodetype", true, false,
+            uuid.setProperty("info",
+                    "Oak index for UUID lookup (direct lookup of nodes with the mixin 'mix:referenceable').");
+            NodeBuilder nodetype = IndexUtils.createIndexDefinition(index, "nodetype", true, false,
                     ImmutableList.of(JCR_PRIMARYTYPE, JCR_MIXINTYPES), null);
+            nodetype.setProperty("info", 
+                    "Oak index for queries with node type, and possibly path restrictions, " + 
+                    "for example \"/jcr:root/content//element(*, mix:language)\".");
             IndexUtils.createReferenceIndex(index);
             
             index.child("counter")
                     .setProperty(JCR_PRIMARYTYPE, INDEX_DEFINITIONS_NODE_TYPE, NAME)
                     .setProperty(TYPE_PROPERTY_NAME, NodeCounterEditorProvider.TYPE)
                     .setProperty(IndexConstants.ASYNC_PROPERTY_NAME, 
-                            IndexConstants.ASYNC_PROPERTY_NAME);
+                            IndexConstants.ASYNC_PROPERTY_NAME)
+                    .setProperty("info", "Oak index that allows to estimate " + 
+                            "how many nodes are stored below a given path, " + 
+                            "to decide whether traversing or using an index is faster.");
         }
 
         // squeeze node state before it is passed to store (OAK-2411)

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/authorization/AuthorizationInitializer.java Wed Aug 17 14:21:07 2016
@@ -45,9 +45,12 @@ class AuthorizationInitializer implement
         // property index for rep:principalName stored in ACEs
         NodeBuilder index = IndexUtils.getOrCreateOakIndex(builder);
         if (!index.hasChildNode("acPrincipalName")) {
-            IndexUtils.createIndexDefinition(index, "acPrincipalName", true, false,
+            NodeBuilder acPrincipalName = IndexUtils.createIndexDefinition(index, "acPrincipalName", true, false,
                     ImmutableList.<String>of(REP_PRINCIPAL_NAME),
                     ImmutableList.<String>of(NT_REP_DENY_ACE, NT_REP_GRANT_ACE, NT_REP_ACE));
+            acPrincipalName.setProperty("info",
+                    "Oak index used by authorization to quickly search a principal by name."
+                    );
         }
 
         // create the permission store and the root for this workspace.

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalConfigurationImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalConfigurationImpl.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalConfigurationImpl.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalConfigurationImpl.java Wed Aug 17 14:21:07 2016
@@ -42,6 +42,7 @@ import org.apache.jackrabbit.oak.spi.sec
 @Service({PrincipalConfiguration.class, SecurityConfiguration.class})
 public class PrincipalConfigurationImpl extends ConfigurationBase implements PrincipalConfiguration {
 
+    @SuppressWarnings("UnusedDeclaration")
     public PrincipalConfigurationImpl() {
         super();
     }
@@ -69,7 +70,14 @@ public class PrincipalConfigurationImpl
     @Override
     public PrincipalProvider getPrincipalProvider(Root root, NamePathMapper namePathMapper) {
         UserConfiguration uc = getSecurityProvider().getConfiguration(UserConfiguration.class);
-        return new PrincipalProviderImpl(root, uc, namePathMapper);
+        PrincipalProvider principalProvider = uc.getUserPrincipalProvider(root, namePathMapper);
+        if (principalProvider != null) {
+            // use user-implementation specific principal provider implementation
+            return principalProvider;
+        } else {
+            // use default implementation acting on user management API
+            return new PrincipalProviderImpl(root, uc, namePathMapper);
+        }
     }
 
     //----------------------------------------------< SecurityConfiguration >---

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/principal/PrincipalProviderImpl.java Wed Aug 17 14:21:07 2016
@@ -34,13 +34,13 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Query;
 import org.apache.jackrabbit.api.security.user.QueryBuilder;
-import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
 import org.apache.jackrabbit.oak.spi.security.principal.PrincipalProvider;
+import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
 import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration;
 import org.apache.jackrabbit.oak.spi.security.user.UserConstants;
 import org.slf4j.Logger;
@@ -167,27 +167,12 @@ class PrincipalProviderImpl implements P
             @Override
             public <T> void build(QueryBuilder<T> builder) {
                 builder.setCondition(builder.like('@' +UserConstants.REP_PRINCIPAL_NAME, buildSearchPattern(nameHint)));
-                builder.setSelector(getAuthorizableClass(searchType));
+                builder.setSelector(AuthorizableType.getType(searchType).getAuthorizableClass());
             }
         };
         return userManager.findAuthorizables(userQuery);
     }
 
-
-    private static Class<? extends Authorizable> getAuthorizableClass(int searchType) {
-        switch (searchType) {
-            case PrincipalManager.SEARCH_TYPE_GROUP:
-                return org.apache.jackrabbit.api.security.user.Group.class;
-            case PrincipalManager.SEARCH_TYPE_NOT_GROUP:
-                return User.class;
-            case PrincipalManager.SEARCH_TYPE_ALL:
-                return Authorizable.class;
-            default:
-                throw new IllegalArgumentException("Invalid search type " + searchType);
-
-        }
-    }
-
     private static String buildSearchPattern(String nameHint) {
         if (nameHint == null) {
             return "%";

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/GroupImpl.java Wed Aug 17 14:21:07 2016
@@ -17,23 +17,29 @@
 package org.apache.jackrabbit.oak.security.user;
 
 import java.security.Principal;
-import java.util.Enumeration;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.ConstraintViolationException;
 
-import com.google.common.base.Function;
 import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
+import com.google.common.base.Strings;
 import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.jackrabbit.api.security.user.Group;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.jackrabbit.commons.iterator.RangeIteratorAdapter;
 import org.apache.jackrabbit.oak.api.Tree;
-import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
 import org.apache.jackrabbit.oak.spi.security.user.AuthorizableType;
 import org.apache.jackrabbit.oak.spi.security.user.util.UserUtil;
+import org.apache.jackrabbit.oak.spi.xml.ImportBehavior;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -42,9 +48,6 @@ import org.slf4j.LoggerFactory;
  */
 class GroupImpl extends AuthorizableImpl implements Group {
 
-    /**
-     * logger instance
-     */
     private static final Logger log = LoggerFactory.getLogger(GroupImpl.class);
 
     GroupImpl(String id, Tree tree, UserManagerImpl userManager) throws RepositoryException {
@@ -110,33 +113,21 @@ class GroupImpl extends AuthorizableImpl
                 log.debug(msg);
                 return false;
             }
-            if (isCyclicMembership(authorizableImpl)) {
-                log.warn("Attempt to create circular group membership.");
-                return false;
-            }
+            // NOTE: detection of circular membership is postponed to the commit (=> UserValidator)
         }
 
-        return getMembershipProvider().addMember(getTree(), authorizableImpl.getTree());
-    }
+        boolean success = getMembershipProvider().addMember(getTree(), authorizableImpl.getTree());
 
-    /**
-     * Returns {@code true} if the given {@code newMember} is a Group
-     * and contains {@code this} Group as declared or inherited member.
-     *
-     * @param newMember The new member to be tested for cyclic membership.
-     * @return true if the 'newMember' is a group and 'this' is an declared or
-     * inherited member of it.
-     */
-    private boolean isCyclicMembership(AuthorizableImpl newMember) {
-        if (newMember.isGroup()) {
-            MembershipProvider mProvider = getMembershipProvider();
-            String contentId = mProvider.getContentID(getTree());
-            if (mProvider.isMember(newMember.getTree(), contentId, true)) {
-                // found cyclic group membership
-                return true;
-            }
+        if (success) {
+            getUserManager().onGroupUpdate(this, false, authorizable);
         }
-        return false;
+
+        return success;
+    }
+
+    @Override
+    public Set<String> addMembers(@Nonnull String... memberIds) throws RepositoryException {
+        return updateMembers(false, memberIds);
     }
 
     @Override
@@ -149,10 +140,22 @@ class GroupImpl extends AuthorizableImpl
             return false;
         } else {
             Tree memberTree = ((AuthorizableImpl) authorizable).getTree();
-            return getMembershipProvider().removeMember(getTree(), memberTree);
+
+            boolean success = getMembershipProvider().removeMember(getTree(), memberTree);
+
+            if (success) {
+                getUserManager().onGroupUpdate(this, true, authorizable);
+            }
+
+            return success;
         }
     }
 
+    @Override
+    public Set<String> removeMembers(@Nonnull String... memberIds) throws RepositoryException {
+        return updateMembers(true, memberIds);
+    }
+
     //--------------------------------------------------------------------------
     /**
      * Internal implementation of {@link #getDeclaredMembers()} and {@link #getMembers()}.
@@ -215,82 +218,118 @@ class GroupImpl extends AuthorizableImpl
             return false;
         } else if (isEveryone()) {
             return true;
+        } else if (((AuthorizableImpl) authorizable).isEveryone()) {
+            return false;
         } else {
             Tree authorizableTree = ((AuthorizableImpl) authorizable).getTree();
             MembershipProvider mgr = getUserManager().getMembershipProvider();
-            return mgr.isMember(this.getTree(), authorizableTree, includeInherited);
+            if (includeInherited) {
+                return mgr.isMember(this.getTree(), authorizableTree);
+            } else {
+                return mgr.isDeclaredMember(this.getTree(), authorizableTree);
+            }
+        }
+    }
+
+    /**
+     * Internal method to add or remove members by ID.
+     *
+     * @param isRemove Boolean flag indicating if members should be added or removed.
+     * @param memberIds The {@code memberIds} to be added or removed.
+     * @return The sub-set of {@code memberIds} that could not be added/removed.
+     * @throws javax.jcr.nodetype.ConstraintViolationException If any of the specified
+     * IDs is empty string or null or if {@link org.apache.jackrabbit.oak.spi.xml.ImportBehavior#ABORT}
+     * is configured and an ID cannot be resolved to an existing (or accessible)
+     * authorizable.
+     * @throws javax.jcr.RepositoryException If another error occurs.
+     */
+    private Set<String> updateMembers(boolean isRemove, @Nonnull String... memberIds) throws RepositoryException {
+        Set<String> idSet = Sets.newLinkedHashSet(Lists.newArrayList(memberIds));
+        int importBehavior = UserUtil.getImportBehavior(getUserManager().getConfig());
+
+        if (isEveryone()) {
+            String msg = "Attempt to add or remove from everyone group.";
+            log.debug(msg);
+            return idSet;
+        }
+
+        Map<String, String> updateMap = Maps.newHashMapWithExpectedSize(idSet.size());
+        Iterator<String> idIterator = idSet.iterator();
+        while (idIterator.hasNext()) {
+            String memberId = idIterator.next();
+            if (Strings.isNullOrEmpty(memberId)) {
+                throw new ConstraintViolationException("MemberId must not be null or empty.");
+            }
+            if (getID().equals(memberId)) {
+                String msg = "Attempt to add or remove a group as member of itself (" + getID() + ").";
+                log.debug(msg);
+                continue;
+            }
+
+            if (ImportBehavior.BESTEFFORT != importBehavior) {
+                Authorizable member = getUserManager().getAuthorizable(memberId);
+                if (member == null) {
+                    if (ImportBehavior.ABORT == importBehavior) {
+                        throw new ConstraintViolationException("Attempt to add or remove a non-existing member " + memberId);
+                    } else if (ImportBehavior.IGNORE == importBehavior) {
+                        String msg = "Attempt to add or remove non-existing member '" + getID() + "' with ImportBehavior = IGNORE.";
+                        log.debug(msg);
+                        continue;
+                    }
+                } else if (member.isGroup() && ((AuthorizableImpl) member).isEveryone()) {
+                    log.debug("Attempt to add everyone group as member.");
+                    continue;
+                }
+            }
+
+            idIterator.remove();
+            updateMap.put(AuthorizableBaseProvider.getContentID(memberId), memberId);
         }
+
+        Set<String> processedIds = Sets.newHashSet(updateMap.values());
+        if (!updateMap.isEmpty()) {
+            Set<String> failedIds;
+            if (isRemove) {
+                failedIds = getMembershipProvider().removeMembers(getTree(), updateMap);
+            } else {
+                failedIds = getMembershipProvider().addMembers(getTree(), updateMap);
+            }
+            idSet.addAll(failedIds);
+            processedIds.removeAll(failedIds);
+        }
+
+        getUserManager().onGroupUpdate(this, isRemove, false, processedIds, idSet);
+        return idSet;
     }
 
     /**
      * Principal representation of this group instance.
      */
-    private class GroupPrincipal extends TreeBasedPrincipal implements java.security.acl.Group {
+    private class GroupPrincipal extends AbstractGroupPrincipal {
 
-        GroupPrincipal(String principalName, Tree groupTree) {
-            super(principalName, groupTree, getUserManager().getNamePathMapper());
+        private GroupPrincipal(String principalName, Tree groupTree) {
+            super(principalName, groupTree, GroupImpl.this.getUserManager().getNamePathMapper());
         }
 
         @Override
-        public boolean addMember(Principal principal) {
-            throw new UnsupportedOperationException();
+        UserManager getUserManager() {
+            return GroupImpl.this.getUserManager();
         }
 
         @Override
-        public boolean removeMember(Principal principal) {
-            throw new UnsupportedOperationException();
+        boolean isEveryone() throws RepositoryException {
+            return GroupImpl.this.isEveryone();
         }
 
         @Override
-        public boolean isMember(Principal principal) {
-            boolean isMember = false;
-            try {
-                // shortcut for everyone group -> avoid collecting all members
-                // as all users and groups are member of everyone.
-                if (isEveryone()) {
-                    isMember = !EveryonePrincipal.NAME.equals(principal.getName());
-                } else {
-                    Authorizable a = getUserManager().getAuthorizable(principal);
-                    if (a != null) {
-                        isMember = GroupImpl.this.isMember(a);
-                    }
-                }
-            } catch (RepositoryException e) {
-                log.warn("Failed to determine group membership", e.getMessage());
-            }
-
-            // principal doesn't represent a known authorizable or an error occurred.
-            return isMember;
+        boolean isMember(@Nonnull Authorizable authorizable) throws RepositoryException {
+            return GroupImpl.this.isMember(authorizable);
         }
 
+        @Nonnull
         @Override
-        public Enumeration<? extends Principal> members() {
-            final Iterator<Authorizable> members;
-            try {
-                members = GroupImpl.this.getMembers();
-            } catch (RepositoryException e) {
-                // should not occur.
-                String msg = "Unable to retrieve Group members: " + e.getMessage();
-                log.error(msg);
-                throw new IllegalStateException(msg);
-            }
-
-            Iterator<Principal> principals = Iterators.transform(members, new Function<Authorizable, Principal>() {
-                @Override
-                public Principal apply(Authorizable authorizable) {
-                    if (authorizable == null) {
-                        return null;
-                    }
-                    try {
-                        return authorizable.getPrincipal();
-                    } catch (RepositoryException e) {
-                        String msg = "Internal error while retrieving principal: " + e.getMessage();
-                        log.error(msg);
-                        throw new IllegalStateException(msg);
-                    }
-                }
-            });
-            return Iterators.asEnumeration(Iterators.filter(principals, Predicates.<Object>notNull()));
+        Iterator<Authorizable> getMembers() throws RepositoryException {
+            return GroupImpl.this.getMembers();
         }
     }
 }
\ No newline at end of file

Modified: jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java?rev=1756639&r1=1756638&r2=1756639&view=diff
==============================================================================
--- jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java (original)
+++ jackrabbit/oak/branches/1.2/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/MembershipProvider.java Wed Aug 17 14:21:07 2016
@@ -16,9 +16,13 @@
  */
 package org.apache.jackrabbit.oak.security.user;
 
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import javax.jcr.RepositoryException;
 
@@ -111,7 +115,7 @@ class MembershipProvider extends Authori
      * @param root the current root
      * @param config the security configuration
      */
-    MembershipProvider(Root root, ConfigurationParameters config) {
+    MembershipProvider(@Nonnull Root root, @Nonnull ConfigurationParameters config) {
         super(root, config);
     }
 
@@ -139,7 +143,7 @@ class MembershipProvider extends Authori
      * @return an iterator over all membership paths.
      */
     @Nonnull
-    Iterator<String> getMembership(Tree authorizableTree, final boolean includeInherited) {
+    Iterator<String> getMembership(@Nonnull Tree authorizableTree, final boolean includeInherited) {
         return getMembership(authorizableTree, includeInherited, new HashSet<String>());
     }
 
@@ -152,63 +156,60 @@ class MembershipProvider extends Authori
      * @return an iterator over all membership paths.
      */
     @Nonnull
-    private Iterator<String> getMembership(Tree authorizableTree, final boolean includeInherited,
-                                           final Set<String> processedPaths) {
+    private Iterator<String> getMembership(@Nonnull Tree authorizableTree, final boolean includeInherited,
+                                           @Nonnull final Set<String> processedPaths) {
         final Iterable<String> refPaths = identifierManager.getReferences(
-                true, authorizableTree, REP_MEMBERS, NT_REP_MEMBER_REFERENCES
+                authorizableTree, REP_MEMBERS, NT_REP_MEMBER_REFERENCES, true
         );
 
-        return new AbstractLazyIterator<String>() {
-
-            private final Iterator<String> references = refPaths.iterator();
-
-            private Iterator<String> parent;
-
+        return new AbstractMemberIterator(refPaths.iterator()) {
             @Override
-            protected String getNext() {
+            protected String internalGetNext(@Nonnull String propPath) {
                 String next = null;
-                while (next == null) {
-                    if (parent != null) {
-                        // if we have a parent iterator, process it first
-                        if (parent.hasNext()) {
-                            next = parent.next();
-                        } else {
-                            parent = null;
-                        }
-                    } else if (!references.hasNext()) {
-                        // if not, check if we have more references to process and abort if not
-                        break;
-                    } else {
-                        // get the next rep:members property path
-                        String propPath = references.next();
-                        int index = propPath.indexOf('/' + REP_MEMBERS_LIST);
-                        if (index < 0) {
-                            index = propPath.indexOf('/' + REP_MEMBERS);
-                        }
-                        if (index > 0) {
-                            String groupPath = propPath.substring(0, index);
-                            if (processedPaths.add(groupPath)) {
-                                // we didn't see this path before, so continue
-                                next = groupPath;
-                                if (includeInherited) {
-                                    // inject a parent iterator of the inherited memberships is needed
-                                    Tree group = getByPath(groupPath);
-                                    if (UserUtil.isType(group, AuthorizableType.GROUP)) {
-                                        parent = getMembership(group, true, processedPaths);
-                                    }
-                                }
+                int index = propPath.indexOf('/' + REP_MEMBERS_LIST);
+                if (index < 0) {
+                    index = propPath.indexOf('/' + REP_MEMBERS);
+                }
+                if (index > 0) {
+                    String groupPath = propPath.substring(0, index);
+                    if (processedPaths.add(groupPath)) {
+                        // we didn't see this path before, so continue
+                        next = groupPath;
+                        if (includeInherited) {
+                            // inject a parent iterator of the inherited memberships is needed
+                            Tree group = getByPath(groupPath);
+                            if (UserUtil.isType(group, AuthorizableType.GROUP)) {
+                                remember(group);
                             }
-                        } else {
-                            log.debug("Not a membership reference property " + propPath);
                         }
                     }
+                } else {
+                    log.debug("Not a membership reference property " + propPath);
                 }
                 return next;
             }
+
+            @Nonnull
+            @Override
+            protected Iterator<String> getNextIterator(@Nonnull Tree groupTree) {
+                return getMembership(groupTree, true, processedPaths);
+            }
         };
     }
 
     /**
+     * Tests if the membership of the specified {@code authorizableTree}
+     * contains the given target group as defined by {@code groupTree}.
+     *
+     * @param authorizableTree The tree of the authorizable for which to resolve the membership.
+     * @param groupPath The path of the group which needs to be tested.
+     * @return {@code true} if the group is contained in the membership of the specified authorizable.
+     */
+    private boolean hasMembership(@Nonnull Tree authorizableTree, @Nonnull String groupPath) {
+        return Iterators.contains(getMembership(authorizableTree, true), groupPath);
+    }
+
+    /**
      * Returns an iterator over all member paths of the given group.
      *
      * @param groupTree the group tree
@@ -233,47 +234,39 @@ class MembershipProvider extends Authori
     @Nonnull
     private Iterator<String> getMembers(@Nonnull final Tree groupTree, @Nonnull final AuthorizableType authorizableType,
                                         final boolean includeInherited, @Nonnull final Set<String> processedRefs) {
+        MemberReferenceIterator mrit = new MemberReferenceIterator(groupTree) {
+            @Override
+            protected boolean hasProcessedReference(@Nonnull String value) {
+                return processedRefs.add(value);
+            }
+        };
 
-        return new AbstractLazyIterator<String>() {
-
-            private MemberReferenceIterator references = new MemberReferenceIterator(groupTree, processedRefs);
-
-            private Iterator<String> parent;
+        return new AbstractMemberIterator(mrit) {
 
             @Override
-            protected String getNext() {
-                String next = null;
-                while (next == null) {
-                    // process parent iterators first
-                    if (parent != null) {
-                        if (parent.hasNext()) {
-                            next = parent.next();
-                        } else {
-                            parent = null;
-                        }
-                    } else if (!references.hasNext()) {
-                        // if there are no more values left, reset the iterator
-                        break;
-                    } else {
-                        String value = references.next();
-                        next = identifierManager.getPath(PropertyValues.newWeakReference(value));
+            protected String internalGetNext(@Nonnull String value) {
+                String next = identifierManager.getPath(PropertyValues.newWeakReference(value));
 
-                        // filter by authorizable type, and/or get inherited members
-                        if (next != null && (includeInherited || authorizableType != AuthorizableType.AUTHORIZABLE)) {
-                            Tree auth = getByPath(next);
-                            AuthorizableType type = (auth == null) ? null : UserUtil.getType(auth);
+                // filter by authorizable type, and/or get inherited members
+                if (next != null && (includeInherited || authorizableType != AuthorizableType.AUTHORIZABLE)) {
+                    Tree auth = getByPath(next);
+                    AuthorizableType type = (auth == null) ? null : UserUtil.getType(auth);
 
-                            if (includeInherited && type == AuthorizableType.GROUP) {
-                                parent = getMembers(auth, authorizableType, true, processedRefs);
-                            }
-                            if (authorizableType != AuthorizableType.AUTHORIZABLE && type != authorizableType) {
-                                next = null;
-                            }
-                        }
+                    if (includeInherited && type == AuthorizableType.GROUP) {
+                        remember(auth);
+                    }
+                    if (authorizableType != AuthorizableType.AUTHORIZABLE && type != authorizableType) {
+                        next = null;
                     }
                 }
                 return next;
             }
+
+            @Nonnull
+            @Override
+            protected Iterator<String> getNextIterator(@Nonnull Tree groupTree) {
+                return getMembers(groupTree, authorizableType, true, processedRefs);
+            }
         };
     }
 
@@ -282,41 +275,61 @@ class MembershipProvider extends Authori
      *
      * @param groupTree  The new member to be tested for cyclic membership.
      * @param authorizableTree The authorizable to check
-     * @param includeInherited {@code true} to also check inherited members
      *
      * @return true if the group has given member.
      */
-    boolean isMember(Tree groupTree, Tree authorizableTree, boolean includeInherited) {
-        return isMember(groupTree, getContentID(authorizableTree), includeInherited);
+    boolean isMember(@Nonnull Tree groupTree, @Nonnull Tree authorizableTree) {
+        if (!hasMembers(groupTree)) {
+            return false;
+        }
+        if (pendingChanges(groupTree)) {
+            return Iterators.contains(getMembers(groupTree, AuthorizableType.AUTHORIZABLE, true), authorizableTree.getPath());
+        } else {
+            return hasMembership(authorizableTree, groupTree.getPath());
+        }
+    }
+
+    boolean isDeclaredMember(@Nonnull Tree groupTree, @Nonnull Tree authorizableTree) {
+        if (!hasMembers(groupTree)) {
+            return false;
+        }
+
+        String contentId = getContentID(authorizableTree);
+        MemberReferenceIterator refs = new MemberReferenceIterator(groupTree) {
+            @Override
+            protected boolean hasProcessedReference(@Nonnull String value) {
+                return true;
+            }
+        };
+        return Iterators.contains(refs, contentId);
     }
 
     /**
-     * Returns {@code true} if the given {@code groupTree} contains a member with the given {@code contentId}
-     *
-     * @param groupTree  The new member to be tested for cyclic membership.
-     * @param contentId The content ID of the group.
-     * @param includeInherited {@code true} to also check inherited members
+     * Utility to determine if a given group has any members.
      *
-     * @return true if the group has given member.
+     * @param groupTree The tree of the target group.
+     * @return {@code true} if the group has any members i.e. if it has a rep:members
+     * property or a rep:membersList child node.
      */
-    boolean isMember(Tree groupTree, String contentId, boolean includeInherited) {
-        if (includeInherited) {
-            Set<String> refs = new HashSet<String>();
-            for (Iterator<String> it = getMembers(groupTree, AuthorizableType.AUTHORIZABLE, includeInherited, refs); it.hasNext();) {
-                it.next();
-                if (refs.contains(contentId)) {
-                    return true;
-                }
-            }
-        } else {
-            MemberReferenceIterator refs = new MemberReferenceIterator(groupTree, new HashSet<String>());
-            while (refs.hasNext()) {
-                if (contentId.equals(refs.next())) {
-                    return true;
-                }
-            }
-        }
-        return false;
+    private static boolean hasMembers(@Nonnull Tree groupTree) {
+        return groupTree.getPropertyStatus(REP_MEMBERS) != null || groupTree.hasChild(REP_MEMBERS_LIST);
+    }
+
+    /**
+     * Determine if the group has (potentially) been modified in which case the
+     * query can't be used:
+     * - rep:members property has been modified
+     * - any potential modification in the member-ref-list subtree, which is not
+     * easy to detect => relying on pending changes on the root object
+     *
+     * @param groupTree The tree of the target group.
+     * @return {@code true} if the specified group tree has an unmodified rep:members
+     * property or if the root has pending changes.
+     */
+    private boolean pendingChanges(@Nonnull Tree groupTree) {
+        Tree.Status memberPropStatus = groupTree.getPropertyStatus(REP_MEMBERS);
+        // rep:members is new or has been modified or root has pending changes
+        return Tree.Status.UNCHANGED != memberPropStatus || root.hasPendingChanges();
     }
 
     /**
@@ -326,19 +339,19 @@ class MembershipProvider extends Authori
      * @return {@code true} if the member was added
      * @throws RepositoryException if an error occurs
      */
-    boolean addMember(Tree groupTree, Tree newMemberTree) throws RepositoryException {
+    boolean addMember(@Nonnull Tree groupTree, @Nonnull Tree newMemberTree) throws RepositoryException {
         return writer.addMember(groupTree, getContentID(newMemberTree));
     }
 
     /**
-     * Adds a new member to the given {@code groupTree}.
-     * @param groupTree the group to add the member to
-     * @param memberContentId the id of the new member
-     * @return {@code true} if the member was added
-     * @throws RepositoryException if an error occurs
+     * Add the members from the given group.
+     *
+     * @param groupTree group to add the new members
+     * @param memberIds Map of 'contentId':'memberId' of all members to be added.
+     * @return the set of member IDs that was not successfully processed.
      */
-    boolean addMember(Tree groupTree, String memberContentId) throws RepositoryException {
-        return writer.addMember(groupTree, memberContentId);
+    Set<String> addMembers(@Nonnull Tree groupTree, @Nonnull Map<String, String> memberIds) throws RepositoryException {
+        return writer.addMembers(groupTree, memberIds);
     }
 
     /**
@@ -348,7 +361,7 @@ class MembershipProvider extends Authori
      * @param memberTree member to remove
      * @return {@code true} if the member was removed.
      */
-    boolean removeMember(Tree groupTree, Tree memberTree) {
+    boolean removeMember(@Nonnull Tree groupTree, @Nonnull Tree memberTree) {
         if (writer.removeMember(groupTree, getContentID(memberTree))) {
             return true;
         } else {
@@ -358,18 +371,25 @@ class MembershipProvider extends Authori
     }
 
     /**
-     * Iterator that provides member references based on the rep:members properties of a underlying tree iterator.
+     * Removes the members from the given group.
+     *
+     * @param groupTree group to remove the member from
+     * @param memberIds Map of 'contentId':'memberId' of all members that need to be removed.
+     * @return the set of member IDs that was not successfully processed.
      */
-    private static final class MemberReferenceIterator extends AbstractLazyIterator<String> {
+    Set<String> removeMembers(@Nonnull Tree groupTree, @Nonnull Map<String, String> memberIds) {
+        return writer.removeMembers(groupTree, memberIds);
+    }
 
-        private final Set<String> processedRefs;
+    /**
+     * Iterator that provides member references based on the rep:members properties of a underlying tree iterator.
+     */
+    private abstract class MemberReferenceIterator extends AbstractLazyIterator<String> {
 
         private final Iterator<Tree> trees;
-
         private Iterator<String> propertyValues;
 
-        private MemberReferenceIterator(@Nonnull Tree groupTree, @Nonnull Set<String> processedRefs) {
-            this.processedRefs = processedRefs;
+        private MemberReferenceIterator(@Nonnull Tree groupTree) {
             this.trees = Iterators.concat(
                     Iterators.singletonIterator(groupTree),
                     groupTree.getChild(REP_MEMBERS_LIST).getChildren().iterator()
@@ -380,7 +400,6 @@ class MembershipProvider extends Authori
         protected String getNext() {
             String next = null;
             while (next == null) {
-
                 if (propertyValues == null) {
                     // check if there are more trees that can provide a rep:members property
                     if (!trees.hasNext()) {
@@ -396,12 +415,87 @@ class MembershipProvider extends Authori
                     propertyValues = null;
                 } else {
                     String value = propertyValues.next();
-                    if (processedRefs.add(value)) {
+                    if (hasProcessedReference(value)) {
                         next = value;
                     }
                 }
             }
             return next;
         }
+
+        protected abstract boolean hasProcessedReference(@Nonnull String value);
+    }
+
+    private abstract class AbstractMemberIterator extends AbstractLazyIterator<String> {
+
+        private Iterator<String> references;
+        private List<Tree> groupTrees;
+        private Iterator<String> parent;
+
+        AbstractMemberIterator(@Nonnull Iterator<String> references) {
+            this.references = references;
+        }
+
+        @Override
+        protected String getNext() {
+            String next = null;
+            while (next == null) {
+                if (references.hasNext()) {
+                    next = internalGetNext(references.next());
+                } else if (parent != null) {
+                    if (parent.hasNext()) {
+                        next = parent.next();
+                    } else {
+                        // force retrieval of next parent iterator
+                        parent = null;
+                    }
+                } else {
+                    // try to retrieve the next 'parent' iterator for the first
+                    // group tree remembered in the list.
+                    if (groupTrees == null || groupTrees.isEmpty()) {
+                        // no more parents to process => reset the iterator.
+                        break;
+                    } else {
+                        parent = getNextIterator(groupTrees.remove(0));
+                    }
+                }
+            }
+            return next;
+        }
+
+        /**
+         * Remember a group that needs to be search for references ('parent')
+         * once all 'references' have been processed.
+         *
+         * @param groupTree A tree associated with a group
+         * @see #getNextIterator(Tree)
+         */
+        protected void remember(@Nonnull Tree groupTree) {
+            if (groupTrees == null) {
+                groupTrees = new ArrayList<Tree>();
+            }
+            groupTrees.add(groupTree);
+        }
+
+        /**
+         * Abstract method to obtain the next authorizable path from the given
+         * reference value.
+         *
+         * @param nextReference The next reference as obtained from the iterator.
+         * @return The path of the authorizable identified by {@code nextReference}
+         * or {@code null} if it cannot be resolved.
+         */
+        @CheckForNull
+        protected abstract String internalGetNext(@Nonnull String nextReference);
+
+        /**
+         * Abstract method to retrieve the next member iterator for the given
+         * {@code groupTree}.
+         *
+         * @param groupTree Tree referring to a group.
+         * @return The next member reference 'parent' iterator to be processed.
+         */
+        @Nonnull
+        protected abstract Iterator<String> getNextIterator(@Nonnull Tree groupTree);
     }
 }
\ No newline at end of file



Re: svn commit: r1756639 [1/5] - in /jackrabbit/oak/branches/1.2: ./ oak-commons/ oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/identifier/ oak-core/src/main/java/org/apache/jackrabbit...

Posted by Julian Reschke <ju...@gmx.de>.
On 2016-08-17 16:21, dj@apache.org wrote:
> Author: dj
> Date: Wed Aug 17 14:21:07 2016
> New Revision: 1756639
>
> URL: http://svn.apache.org/viewvc?rev=1756639&view=rev
> Log:
> OAK-4679 : Backport OAK-4119, OAK-4101, OAK-4087 and OAK-4344
> - backported OAK-4119
>   - depends on OAK-4003
>   - depends on OAK-3721
>   - depends on OAK-2742
>   - depends on OAK-3728
>   - depends on OAK-3170
>     - depends on Jackrabbit >= 2.11.0
>     - depends on OAK-2994
>     - depends on OAK-2690
> ...

Wait.

This change updates the base Jackrabbit version to 2.11.0. We can't do 
that - 2.11 is an unstable branch.

Best regards, Julian