Author: mreutegg Date: Wed Aug 22 08:51:41 2018 New Revision: 1838617 URL: http://svn.apache.org/viewvc?rev=1838617&view=rev Log: OAK-7569: Direct Binary Access
Remaining changes from Matt Ryan's PR https://github.com/apache/jackrabbit-oak/pull/96 Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/AbstractBinaryAccessIT.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessDSGCIT.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessIT.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessTest.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessUnsupportedIT.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/datastore/ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/datastore/AzureDataStoreFixture.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/datastore/DataStoreFixture.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/datastore/FileDataStoreFixture.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/datastore/S3DataStoreFixture.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/nodestore/ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/nodestore/DocumentMemoryNodeStoreFixture.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/nodestore/FixtureUtils.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/fixtures/nodestore/SegmentMemoryNodeStoreFixture.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/util/ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/util/BinaryAccessTestUtils.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/util/Content.java (with props) jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/util/ComponentHolder.java (with props) Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImplTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/GroupImplTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/MembershipBaseTest.java jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java jackrabbit/oak/trunk/oak-jcr/pom.xml jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventQueue.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/PropertyImpl.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionImpl.java jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java jackrabbit/oak/trunk/oak-parent/pom.xml jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/BinaryImpl.java jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/PartialValueFactory.java jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueFactoryImpl.java jackrabbit/oak/trunk/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/plugins/value/jcr/ValueImpl.java Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizableImpl.java Wed Aug 22 08:51:41 2018 @@ -230,7 +230,7 @@ abstract class AuthorizableImpl implemen */ private AuthorizableProperties getAuthorizableProperties() { if (properties == null) { - properties = new AuthorizablePropertiesImpl(this, userManager.getNamePathMapper()); + properties = new AuthorizablePropertiesImpl(this, userManager.getPartialValueFactory()); } return properties; } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImpl.java Wed Aug 22 08:51:41 2018 @@ -30,7 +30,6 @@ import org.apache.jackrabbit.JcrConstant import org.apache.jackrabbit.oak.api.PropertyState; import org.apache.jackrabbit.oak.api.Tree; import org.apache.jackrabbit.oak.commons.PathUtils; -import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.memory.PropertyStates; import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager; import org.apache.jackrabbit.oak.plugins.tree.TreeLocation; @@ -53,11 +52,12 @@ class AuthorizablePropertiesImpl impleme private static final Logger log = LoggerFactory.getLogger(AuthorizablePropertiesImpl.class); private final AuthorizableImpl authorizable; - private final NamePathMapper namePathMapper; + private final PartialValueFactory valueFactory; - AuthorizablePropertiesImpl(@NotNull AuthorizableImpl authorizable, @NotNull NamePathMapper namePathMapper) { + AuthorizablePropertiesImpl(@NotNull AuthorizableImpl authorizable, + @NotNull PartialValueFactory valueFactory) { this.authorizable = authorizable; - this.namePathMapper = namePathMapper; + this.valueFactory = valueFactory; } //---------------------------------------------< AuthorizableProperties >--- @@ -73,7 +73,7 @@ class AuthorizablePropertiesImpl impleme for (PropertyState property : parent.getProperties()) { String propName = property.getName(); if (isAuthorizableProperty(tree, location.getChild(propName), false)) { - l.add(namePathMapper.getJcrName(propName)); + l.add(valueFactory.getNamePathMapper().getJcrName(propName)); } } return l.iterator(); @@ -102,10 +102,10 @@ class AuthorizablePropertiesImpl impleme PropertyState property = getAuthorizableProperty(tree, getLocation(tree, oakPath), true); if (property != null) { if (property.isArray()) { - List<Value> vs = new PartialValueFactory(namePathMapper).createValues(property); + List<Value> vs = valueFactory.createValues(property); values = vs.toArray(new Value[vs.size()]); } else { - values = new Value[]{new PartialValueFactory(namePathMapper).createValue(property)}; + values = new Value[]{valueFactory.createValue(property)}; } } return values; @@ -298,7 +298,7 @@ class AuthorizablePropertiesImpl impleme if (relPath == null || relPath.isEmpty() || relPath.charAt(0) == '/') { throw new RepositoryException("Relative path expected. Found " + relPath); } - String oakPath = namePathMapper.getOakPath(relPath); + String oakPath = valueFactory.getNamePathMapper().getOakPath(relPath); if (oakPath == null) { throw new RepositoryException("Failed to resolve relative path: " + relPath); } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserConfigurationImpl.java Wed Aug 22 08:51:41 2018 @@ -25,7 +25,9 @@ import java.util.Set; import com.google.common.collect.ImmutableList; import org.apache.jackrabbit.api.security.user.UserManager; import org.apache.jackrabbit.oak.api.Root; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.namepath.NamePathMapper; +import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory; import org.apache.jackrabbit.oak.security.user.autosave.AutoSaveEnabledManager; import org.apache.jackrabbit.oak.spi.commit.MoveTracker; import org.apache.jackrabbit.oak.spi.commit.ThreeWayConflictHandler; @@ -41,17 +43,24 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; import org.apache.jackrabbit.oak.spi.security.user.util.PasswordUtil; +import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; +import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardAware; +import org.apache.jackrabbit.oak.spi.whiteboard.WhiteboardUtils; import org.apache.jackrabbit.oak.spi.xml.ImportBehavior; import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; +import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.metatype.annotations.AttributeDefinition; import org.osgi.service.metatype.annotations.Designate; import org.osgi.service.metatype.annotations.ObjectClassDefinition; import org.osgi.service.metatype.annotations.Option; +import static org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory.DEFAULT_BLOB_ACCESS_PROVIDER; + /** * Default implementation of the {@link UserConfiguration}. */ @@ -176,6 +185,9 @@ public class UserConfigurationImpl exten setParameters(ConfigurationParameters.of(properties)); } + @Reference(cardinality = ReferenceCardinality.OPTIONAL) + private BlobAccessProvider blobAccessProvider; + //----------------------------------------------< SecurityConfiguration >--- @NotNull @Override @@ -230,7 +242,8 @@ public class UserConfigurationImpl exten @NotNull @Override public UserManager getUserManager(Root root, NamePathMapper namePathMapper) { - UserManager umgr = new UserManagerImpl(root, namePathMapper, getSecurityProvider()); + PartialValueFactory vf = new PartialValueFactory(namePathMapper, getBlobAccessProvider()); + UserManager umgr = new UserManagerImpl(root, vf, getSecurityProvider()); if (getParameters().getConfigValue(UserConstants.PARAM_SUPPORT_AUTOSAVE, false)) { return new AutoSaveEnabledManager(umgr, root); } else { @@ -243,4 +256,24 @@ public class UserConfigurationImpl exten public PrincipalProvider getUserPrincipalProvider(@NotNull Root root, @NotNull NamePathMapper namePathMapper) { return new UserPrincipalProvider(root, this, namePathMapper); } + + //-----------------------------------------------------------< internal >--- + + private BlobAccessProvider getBlobAccessProvider() { + BlobAccessProvider provider = blobAccessProvider; + if (provider == null) { + SecurityProvider securityProvider = getSecurityProvider(); + if (securityProvider instanceof WhiteboardAware) { + Whiteboard wb = ((WhiteboardAware) securityProvider).getWhiteboard(); + if (wb != null) { + provider = WhiteboardUtils.getService(wb, BlobAccessProvider.class); + } + } + } + if (provider == null) { + provider = DEFAULT_BLOB_ACCESS_PROVIDER; + blobAccessProvider = provider; + } + return provider; + } } Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserImporter.java Wed Aug 22 08:51:41 2018 @@ -50,6 +50,7 @@ import org.apache.jackrabbit.oak.api.Typ import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager; import org.apache.jackrabbit.oak.plugins.memory.PropertyStates; +import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory; import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants; import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; @@ -193,7 +194,7 @@ class UserImporter implements ProtectedP return false; } - userManager = new UserManagerImpl(root, namePathMapper, securityProvider); + userManager = new UserManagerImpl(root, new PartialValueFactory(namePathMapper), securityProvider); initialized = true; return initialized; Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java (original) +++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/UserManagerImpl.java Wed Aug 22 08:51:41 2018 @@ -39,6 +39,7 @@ import org.apache.jackrabbit.oak.api.Tre import org.apache.jackrabbit.oak.api.Type; import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.nodetype.ReadOnlyNodeTypeManager; +import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory; import org.apache.jackrabbit.oak.security.user.query.UserQueryManager; import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters; import org.apache.jackrabbit.oak.spi.security.SecurityProvider; @@ -68,6 +69,7 @@ public class UserManagerImpl implements private static final Logger log = LoggerFactory.getLogger(UserManagerImpl.class); private final Root root; + private final PartialValueFactory valueFactory; private final NamePathMapper namePathMapper; private final SecurityProvider securityProvider; @@ -79,10 +81,12 @@ public class UserManagerImpl implements private UserQueryManager queryManager; private ReadOnlyNodeTypeManager ntMgr; - public UserManagerImpl(@NotNull Root root, @NotNull NamePathMapper namePathMapper, + public UserManagerImpl(@NotNull Root root, + @NotNull PartialValueFactory valueFactory, @NotNull SecurityProvider securityProvider) { this.root = root; - this.namePathMapper = namePathMapper; + this.valueFactory = valueFactory; + this.namePathMapper = valueFactory.getNamePathMapper(); this.securityProvider = securityProvider; UserConfiguration uc = securityProvider.getConfiguration(UserConfiguration.class); @@ -377,6 +381,11 @@ public class UserManagerImpl implements } @NotNull + PartialValueFactory getPartialValueFactory() { + return valueFactory; + } + + @NotNull ReadOnlyNodeTypeManager getNodeTypeManager() { if (ntMgr == null) { ntMgr = ReadOnlyNodeTypeManager.getInstance(root, NamePathMapper.DEFAULT); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java Wed Aug 22 08:51:41 2018 @@ -53,6 +53,7 @@ import org.apache.jackrabbit.oak.plugins import org.apache.jackrabbit.oak.plugins.tree.TreeProvider; import org.apache.jackrabbit.oak.plugins.tree.impl.RootProviderService; import org.apache.jackrabbit.oak.plugins.tree.impl.TreeProviderService; +import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory; import org.apache.jackrabbit.oak.plugins.value.jcr.ValueFactoryImpl; import org.apache.jackrabbit.oak.plugins.version.VersionHook; import org.apache.jackrabbit.oak.query.QueryEngineSettings; @@ -80,6 +81,7 @@ public abstract class AbstractSecurityTe private User testUser; protected NamePathMapper namePathMapper = NamePathMapper.DEFAULT; + protected PartialValueFactory valueFactory = new PartialValueFactory(namePathMapper); protected SecurityProvider securityProvider; protected ContentSession adminSession; protected Root root; @@ -179,6 +181,10 @@ public abstract class AbstractSecurityTe return namePathMapper; } + protected PartialValueFactory getPartialValueFactory() { + return valueFactory; + } + protected UserConfiguration getUserConfiguration() { return getConfig(UserConfiguration.class); } Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImplTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImplTest.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImplTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/AuthorizablePropertiesImplTest.java Wed Aug 22 08:51:41 2018 @@ -32,6 +32,7 @@ import org.apache.jackrabbit.api.securit import org.apache.jackrabbit.oak.AbstractSecurityTest; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.namepath.NamePathMapper; +import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory; import org.apache.jackrabbit.oak.spi.nodetype.NodeTypeConstants; import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; @@ -57,7 +58,7 @@ public class AuthorizablePropertiesImplT super.before(); User user = getTestUser(); - emptyProperties = new AuthorizablePropertiesImpl((AuthorizableImpl) user, getNamePathMapper()); + emptyProperties = new AuthorizablePropertiesImpl((AuthorizableImpl) user, getPartialValueFactory()); String id2 = "user2" + UUID.randomUUID().toString(); user2 = getUserManager(root).createUser(id2, null, new PrincipalImpl(id2), PathUtils.getAncestorPath(user.getPath(), 1)); @@ -73,7 +74,7 @@ public class AuthorizablePropertiesImplT user2.setProperty("relPath/mvProp", vArr); root.commit(); - properties = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, getNamePathMapper()); + properties = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, getPartialValueFactory()); } @Override @@ -116,7 +117,8 @@ public class AuthorizablePropertiesImplT @Test(expected = RepositoryException.class) public void testGetNamesMissingResolutionToOakPath() throws Exception { - AuthorizableProperties props = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, new NamePathMapper.Default() { + AuthorizableProperties props = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, + new PartialValueFactory(new NamePathMapper.Default() { @Override public String getOakNameOrNull(@NotNull String jcrName) { return null; @@ -126,7 +128,7 @@ public class AuthorizablePropertiesImplT public String getOakPath(String jcrPath) { return null; } - }); + })); props.getNames("relPath"); } @@ -210,7 +212,8 @@ public class AuthorizablePropertiesImplT @Test(expected = RepositoryException.class) public void testSetMissingResolutionToOakPath() throws Exception { - AuthorizableProperties props = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, new NamePathMapper.Default() { + AuthorizableProperties props = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, + new PartialValueFactory(new NamePathMapper.Default() { @Override public String getOakNameOrNull(@NotNull String jcrName) { return null; @@ -220,7 +223,7 @@ public class AuthorizablePropertiesImplT public String getOakPath(String jcrPath) { return null; } - }); + })); props.setProperty("relPath/prop", vf.createValue("value")); } @@ -279,7 +282,8 @@ public class AuthorizablePropertiesImplT @Test(expected = RepositoryException.class) public void testRemoveMissingResolutionToOakPath() throws Exception { - AuthorizableProperties props = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, new NamePathMapper.Default() { + AuthorizableProperties props = new AuthorizablePropertiesImpl((AuthorizableImpl) user2, + new PartialValueFactory(new NamePathMapper.Default() { @Override public String getOakNameOrNull(@NotNull String jcrName) { return null; @@ -289,7 +293,7 @@ public class AuthorizablePropertiesImplT public String getOakPath(String jcrPath) { return null; } - }); + })); props.removeProperty("relPath/prop"); } Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/GroupImplTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/GroupImplTest.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/GroupImplTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/GroupImplTest.java Wed Aug 22 08:51:41 2018 @@ -44,7 +44,7 @@ public class GroupImplTest extends Abstr public void before() throws Exception { super.before(); - uMgr = new UserManagerImpl(root, getNamePathMapper(), getSecurityProvider()); + uMgr = new UserManagerImpl(root, getPartialValueFactory(), getSecurityProvider()); Group g = uMgr.createGroup(groupId); group = new GroupImpl(groupId, root.getTree(g.getPath()), uMgr); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/MembershipBaseTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/MembershipBaseTest.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/MembershipBaseTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/MembershipBaseTest.java Wed Aug 22 08:51:41 2018 @@ -61,7 +61,7 @@ public abstract class MembershipBaseTest @Before public void before() throws Exception { super.before(); - userMgr = new UserManagerImpl(root, namePathMapper, getSecurityProvider()); + userMgr = new UserManagerImpl(root, getPartialValueFactory(), getSecurityProvider()); mp = userMgr.getMembershipProvider(); // set the threshold low for testing mp.setMembershipSizeThreshold(SIZE_TH); Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java (original) +++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserManagerImplTest.java Wed Aug 22 08:51:41 2018 @@ -66,7 +66,7 @@ public class UserManagerImplTest extends public void before() throws Exception { super.before(); - userMgr = new UserManagerImpl(root, namePathMapper, getSecurityProvider()); + userMgr = new UserManagerImpl(root, getPartialValueFactory(), getSecurityProvider()); beforeAuthorizables.clear(); Iterator<Authorizable> iter = userMgr.findAuthorizables("jcr:primaryType", null, UserManager.SEARCH_TYPE_AUTHORIZABLE); while (iter.hasNext()) { @@ -305,7 +305,7 @@ public class UserManagerImplTest extends try { ContentSession admin = login(getAdminCredentials()); Root root = admin.getLatestRoot(); - UserManager userManager = new UserManagerImpl(root, namePathMapper, getSecurityProvider()); + UserManager userManager = new UserManagerImpl(root, getPartialValueFactory(), getSecurityProvider()); userManager.createUser(userId, "pass"); root.commit(); admin.close(); Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/pom.xml (original) +++ jackrabbit/oak/trunk/oak-jcr/pom.xml Wed Aug 22 08:51:41 2018 @@ -334,6 +334,19 @@ <artifactId>jackrabbit-jcr-commons</artifactId> <version>${jackrabbit.version}</version> </dependency> + + <dependency> + <groupId>org.apache.jackrabbit</groupId> + <artifactId>oak-blob-cloud</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.jackrabbit</groupId> + <artifactId>oak-blob-cloud-azure</artifactId> + <version>${project.version}</version> + <scope>test</scope> + </dependency> <dependency> <groupId>com.google.guava</groupId> Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ChangeProcessor.java Wed Aug 22 08:51:41 2018 @@ -40,6 +40,7 @@ import javax.jcr.observation.EventListen import org.apache.jackrabbit.api.jmx.EventListenerMBean; import org.apache.jackrabbit.commons.observation.ListenerTracker; import org.apache.jackrabbit.oak.api.ContentSession; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.commons.PerfLogger; import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.observation.CommitRateLimiter; @@ -172,6 +173,7 @@ class ChangeProcessor implements Filteri private final TimeSeriesMax maxQueueLengthRecorder; private final int queueLength; private final CommitRateLimiter commitRateLimiter; + private final BlobAccessProvider blobAccessProvider; /** * Lazy initialization via the {@link #start(Whiteboard)} method @@ -206,7 +208,8 @@ class ChangeProcessor implements Filteri FilterProvider filter, StatisticManager statisticManager, int queueLength, - CommitRateLimiter commitRateLimiter) { + CommitRateLimiter commitRateLimiter, + BlobAccessProvider blobAccessProvider) { this.contentSession = contentSession; this.namePathMapper = namePathMapper; this.tracker = tracker; @@ -217,6 +220,7 @@ class ChangeProcessor implements Filteri this.maxQueueLengthRecorder = statisticManager.maxQueLengthRecorder(); this.queueLength = queueLength; this.commitRateLimiter = commitRateLimiter; + this.blobAccessProvider = blobAccessProvider; } /** @@ -492,7 +496,8 @@ class ChangeProcessor implements Filteri // FIXME don't rely on toString for session id if (provider.includeCommit(contentSession.toString(), info)) { EventFilter filter = provider.getFilter(before, after); - EventIterator events = new EventQueue(namePathMapper, info, before, after, + EventIterator events = new EventQueue(namePathMapper, + blobAccessProvider, info, before, after, provider.getSubTrees(), Filters.all(filter, VISIBLE_FILTER), provider.getEventAggregator()); Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventFactory.java Wed Aug 22 08:51:41 2018 @@ -35,10 +35,12 @@ import com.google.common.collect.Immutab import com.google.common.collect.Lists; import org.apache.jackrabbit.api.observation.JackrabbitEvent; import org.apache.jackrabbit.oak.api.PropertyState; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory; import org.apache.jackrabbit.oak.spi.commit.CommitInfo; +import org.jetbrains.annotations.NotNull; /** * Event factory for generating JCR event instances that are optimized @@ -64,9 +66,11 @@ public class EventFactory { private final boolean external; - EventFactory(NamePathMapper mapper, CommitInfo commitInfo) { + EventFactory(@NotNull NamePathMapper mapper, + @NotNull BlobAccessProvider blobAccessProvider, + @NotNull CommitInfo commitInfo) { this.mapper = mapper; - this.valueFactory = new PartialValueFactory(mapper); + this.valueFactory = new PartialValueFactory(mapper, blobAccessProvider); if (!commitInfo.isExternal()) { this.userID = commitInfo.getUserId(); Object userData = commitInfo.getInfo().get(USER_DATA); Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventQueue.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventQueue.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventQueue.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/EventQueue.java Wed Aug 22 08:51:41 2018 @@ -26,6 +26,7 @@ import java.util.NoSuchElementException; import javax.jcr.observation.Event; import javax.jcr.observation.EventIterator; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.namepath.NamePathMapper; import org.apache.jackrabbit.oak.plugins.observation.EventGenerator; @@ -50,12 +51,13 @@ class EventQueue implements EventIterato private long position = 0; public EventQueue( - @NotNull NamePathMapper mapper, CommitInfo info, + @NotNull NamePathMapper mapper, + @NotNull BlobAccessProvider blobAccessProvider, CommitInfo info, @NotNull NodeState before, @NotNull NodeState after, @NotNull Iterable<String> basePaths, @NotNull EventFilter filter, @Nullable EventAggregator aggregator) { this.generator = new EventGenerator(); - EventFactory factory = new EventFactory(mapper, info); + EventFactory factory = new EventFactory(mapper, blobAccessProvider, info); EventHandler handler = new FilteredHandler( filter, new QueueingHandler(this, factory, aggregator, before, after)); for (String path : basePaths) { Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/observation/ObservationManagerImpl.java Wed Aug 22 08:51:41 2018 @@ -49,6 +49,7 @@ import org.apache.jackrabbit.commons.ite import org.apache.jackrabbit.commons.observation.ListenerTracker; import org.apache.jackrabbit.oak.api.ContentSession; import org.apache.jackrabbit.oak.api.Root; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate; import org.apache.jackrabbit.oak.jcr.session.SessionContext; @@ -97,6 +98,7 @@ public class ObservationManagerImpl impl private final int queueLength; private final CommitRateLimiter commitRateLimiter; private final PermissionProviderFactory permissionProviderFactory; + private final BlobAccessProvider blobAccessProvider; /** * Create a new instance based on a {@link ContentSession} that needs to implement @@ -120,6 +122,7 @@ public class ObservationManagerImpl impl this.statisticManager = sessionContext.getStatisticManager(); this.queueLength = queueLength; this.commitRateLimiter = commitRateLimiter; + this.blobAccessProvider = sessionContext.getBlobAccessProvider(); this.permissionProviderFactory = new PermissionProviderFactory() { Set<Principal> principals = sessionDelegate.getAuthInfo().getPrincipals(); @NotNull @@ -161,7 +164,7 @@ public class ObservationManagerImpl impl // session. See OAK-1368. processor = new ChangeProcessor(sessionDelegate.getContentSession(), namePathMapper, tracker, filterProvider, statisticManager, queueLength, - commitRateLimiter); + commitRateLimiter, blobAccessProvider); processors.put(listener, processor); processor.start(whiteboard); } else { Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/query/QueryResultImpl.java Wed Aug 22 08:51:41 2018 @@ -65,7 +65,7 @@ public class QueryResultImpl implements this.sessionContext = sessionContext; this.sessionDelegate = sessionContext.getSessionDelegate(); this.result = result; - this.valueFactory = new PartialValueFactory(sessionContext); + this.valueFactory = new PartialValueFactory(sessionContext, sessionContext.getBlobAccessProvider()); } @Override Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/repository/RepositoryImpl.java Wed Aug 22 08:51:41 2018 @@ -49,6 +49,7 @@ import org.apache.jackrabbit.api.securit import org.apache.jackrabbit.commons.SimpleValueFactory; import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.api.ContentSession; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.api.jmx.SessionMBean; import org.apache.jackrabbit.oak.commons.concurrent.ExecutorCloser; import org.apache.jackrabbit.oak.jcr.delegate.SessionDelegate; @@ -109,6 +110,7 @@ public class RepositoryImpl implements J private final DelegatingGCMonitor gcMonitor = new DelegatingGCMonitor(); private final Registration gcMonitorRegistration; private final MountInfoProvider mountInfoProvider; + private final BlobAccessProvider blobAccessProvider; /** * {@link ThreadLocal} counter that keeps track of the save operations @@ -157,6 +159,7 @@ public class RepositoryImpl implements J this.gcMonitorRegistration = whiteboard.register(GCMonitor.class, gcMonitor, emptyMap()); this.fastQueryResultSize = fastQueryResultSize; this.mountInfoProvider = WhiteboardUtils.getService(whiteboard, MountInfoProvider.class); + this.blobAccessProvider = WhiteboardUtils.getService(whiteboard, BlobAccessProvider.class); } //---------------------------------------------------------< Repository >--- @@ -348,7 +351,7 @@ public class RepositoryImpl implements J Map<String, Object> attributes, SessionDelegate delegate, int observationQueueLength, CommitRateLimiter commitRateLimiter) { return new SessionContext(this, statisticManager, securityProvider, whiteboard, attributes, - delegate, observationQueueLength, commitRateLimiter, mountInfoProvider, fastQueryResultSize); + delegate, observationQueueLength, commitRateLimiter, mountInfoProvider, blobAccessProvider, fastQueryResultSize); } /** Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/PropertyImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/PropertyImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/PropertyImpl.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/PropertyImpl.java Wed Aug 22 08:51:41 2018 @@ -249,7 +249,7 @@ public class PropertyImpl extends ItemIm @NotNull @Override public Value perform() throws RepositoryException { - return new PartialValueFactory(sessionContext) + return new PartialValueFactory(sessionContext, sessionContext.getBlobAccessProvider()) .createValue(property.getSingleState()); } }); @@ -262,7 +262,7 @@ public class PropertyImpl extends ItemIm @NotNull @Override public List<Value> perform() throws RepositoryException { - return new PartialValueFactory(sessionContext) + return new PartialValueFactory(sessionContext, sessionContext.getBlobAccessProvider()) .createValues(property.getMultiState()); } }).toArray(NO_VALUES); Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/session/SessionContext.java Wed Aug 22 08:51:41 2018 @@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.jcr.se import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.Sets.newHashSet; import static com.google.common.collect.Sets.newTreeSet; +import static org.apache.jackrabbit.oak.plugins.value.jcr.PartialValueFactory.DEFAULT_BLOB_ACCESS_PROVIDER; import java.util.ArrayList; import java.util.Iterator; @@ -39,6 +40,7 @@ import org.apache.jackrabbit.api.securit import org.apache.jackrabbit.api.security.principal.PrincipalManager; import org.apache.jackrabbit.api.security.user.UserManager; import org.apache.jackrabbit.api.stats.RepositoryStatistics.Type; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; import org.apache.jackrabbit.oak.jcr.delegate.AccessControlManagerDelegator; import org.apache.jackrabbit.oak.jcr.delegate.JackrabbitAccessControlManagerDelegator; import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate; @@ -63,9 +65,9 @@ import org.apache.jackrabbit.oak.spi.sec import org.apache.jackrabbit.oak.spi.security.user.UserConfiguration; import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; import org.apache.jackrabbit.oak.spi.xml.ProtectedItemImporter; -import org.apache.jackrabbit.oak.stats.StatisticManager; import org.apache.jackrabbit.oak.stats.CounterStats; import org.apache.jackrabbit.oak.stats.MeterStats; +import org.apache.jackrabbit.oak.stats.StatisticManager; import org.apache.jackrabbit.oak.stats.TimerStats; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -104,6 +106,7 @@ public class SessionContext implements N private UserManager userManager; private PrivilegeManager privilegeManager; private ObservationManagerImpl observationManager; + private BlobAccessProvider blobAccessProvider; /** Paths (tokens) of all open scoped locks held by this session. */ private final Set<String> openScopedLocks = newTreeSet(); @@ -120,7 +123,7 @@ public class SessionContext implements N int observationQueueLength, CommitRateLimiter commitRateLimiter) { this(repository, statisticManager, securityProvider, whiteboard, attributes, delegate, - observationQueueLength, commitRateLimiter, null, false); + observationQueueLength, commitRateLimiter, null, null, false); } public SessionContext( @@ -128,7 +131,8 @@ public class SessionContext implements N @NotNull SecurityProvider securityProvider, @NotNull Whiteboard whiteboard, @NotNull Map<String, Object> attributes, @NotNull final SessionDelegate delegate, int observationQueueLength, CommitRateLimiter commitRateLimiter, - MountInfoProvider mountInfoProvider, boolean fastQueryResultSize) { + MountInfoProvider mountInfoProvider, @Nullable BlobAccessProvider blobAccessProvider, + boolean fastQueryResultSize) { this.repository = checkNotNull(repository); this.statisticManager = statisticManager; this.securityProvider = checkNotNull(securityProvider); @@ -138,13 +142,14 @@ public class SessionContext implements N this.observationQueueLength = observationQueueLength; this.commitRateLimiter = commitRateLimiter; this.mountInfoProvider = mountInfoProvider; + this.blobAccessProvider = blobAccessProvider == null ? DEFAULT_BLOB_ACCESS_PROVIDER : blobAccessProvider; SessionStats sessionStats = delegate.getSessionStats(); sessionStats.setAttributes(attributes); this.namePathMapper = new NamePathMapperImpl( delegate.getNamespaces(), delegate.getIdManager()); this.valueFactory = new ValueFactoryImpl( - delegate.getRoot(), namePathMapper); + delegate.getRoot(), namePathMapper, this.blobAccessProvider); this.fastQueryResultSize = fastQueryResultSize; } @@ -298,6 +303,11 @@ public class SessionContext implements N return observationManager; } + @NotNull + public BlobAccessProvider getBlobAccessProvider() { + return blobAccessProvider; + } + public boolean hasEventListeners(){ if (observationManager != null){ return observationManager.getRegisteredEventListeners().hasNext(); Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionImpl.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionImpl.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/version/VersionImpl.java Wed Aug 22 08:51:41 2018 @@ -115,7 +115,8 @@ public class VersionImpl extends NodeImp } private List<Value> getValues(PropertyDelegate p) throws InvalidItemStateException, ValueFormatException { - return new PartialValueFactory(sessionContext).createValues(p.getMultiState()); + return new PartialValueFactory(sessionContext, sessionContext.getBlobAccessProvider()) + .createValues(p.getMultiState()); } @Override Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java?rev=1838617&r1=1838616&r2=1838617&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java (original) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/AbstractRepositoryTest.java Wed Aug 22 08:51:41 2018 @@ -16,9 +16,10 @@ */ package org.apache.jackrabbit.oak.jcr; +import static org.junit.Assume.assumeTrue; import java.util.Collection; +import java.util.Map; import java.util.Set; - import javax.jcr.GuestCredentials; import javax.jcr.Repository; import javax.jcr.RepositoryException; @@ -32,16 +33,21 @@ import org.apache.jackrabbit.oak.NodeSto import org.apache.jackrabbit.oak.commons.FixturesHelper; import org.apache.jackrabbit.oak.commons.FixturesHelper.Fixture; import org.apache.jackrabbit.oak.fixture.NodeStoreFixture; +import org.apache.jackrabbit.oak.jcr.util.ComponentHolder; import org.apache.jackrabbit.oak.plugins.document.bundlor.BundlingConfigInitializer; import org.apache.jackrabbit.oak.query.QueryEngineSettings; import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal; import org.apache.jackrabbit.oak.spi.security.user.UserConstants; import org.apache.jackrabbit.oak.spi.state.NodeStore; import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; import org.junit.Ignore; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import com.google.common.collect.Maps; + /** * Abstract base class for repository tests providing methods for accessing * the repository, a session and nodes and properties from that session. @@ -54,10 +60,12 @@ import org.junit.runners.Parameterized; public abstract class AbstractRepositoryTest { protected final NodeStoreFixture fixture; + private final boolean reuseNodeStore; private volatile NodeStore nodeStore; private volatile Repository repository; private volatile Session adminSession; + private volatile Session anonymousSession; /** * The system property "nsfixtures" can be used to provide a @@ -66,35 +74,95 @@ public abstract class AbstractRepository */ private static final Set<Fixture> FIXTURES = FixturesHelper.getFixtures(); - protected AbstractRepositoryTest(NodeStoreFixture fixture) { - this.fixture = fixture; - } + /** + * If reuseNodeStore is on, this caches the NodeStore returned by each fixture + * and they'll be disposed only in @AfterClass instead of @After. + */ + private static final Map<NodeStoreFixture, NodeStore> NODE_STORES = Maps.newConcurrentMap(); + /** + * Default fixtures based on a list in the system property `nsfixtures`. + * To change the fixtures in a subclass, provide a static method with same @Parameterized + * annotation but different name that returns a different fixture list. + */ @Parameterized.Parameters(name="{0}") public static Collection<Object[]> fixtures() { return NodeStoreFixtures.asJunitParameters(FIXTURES); } + /** + * Constructor enabling that a new NodeStore will be created from + * the NodeStoreFixture for each test (method). + * + * @param fixture the fixture, which gets passed in as junit parameter + */ + protected AbstractRepositoryTest(NodeStoreFixture fixture) { + this(fixture, false); + } + + /** + * Constructor giving a choice on NodeStore reuse across tests. + * + * @param fixture the fixture, which gets passed in as junit parameter + * @param reuseNodeStore if true, the NodeStore will be reused for all test methods of the + * given test class. if false, a new NodeStore will be created from + * the NodeStoreFixture for each test (method). + */ + protected AbstractRepositoryTest(NodeStoreFixture fixture, boolean reuseNodeStore) { + this.fixture = fixture; + this.reuseNodeStore = reuseNodeStore; + } + + @Before + public void ignoreIfFixtureUnavailable() { + assumeTrue("Skipping unavailable fixture: " + fixture.toString(), fixture.isAvailable()); + } + @After public void logout() { - // release session field + // release session fields if (adminSession != null) { adminSession.logout(); adminSession = null; } + if (anonymousSession != null) { + anonymousSession.logout(); + anonymousSession = null; + } // release repository field if (repository instanceof JackrabbitRepository) { ((JackrabbitRepository) repository).shutdown(); } repository = null; - if (nodeStore != null) { + if (nodeStore != null && !reuseNodeStore) { fixture.dispose(nodeStore); } } + @AfterClass + public static void disposeNodeStores() { + // only dispose after the entire class + for (Map.Entry<NodeStoreFixture, NodeStore> e : NODE_STORES.entrySet()) { + e.getKey().dispose(e.getValue()); + } + NODE_STORES.clear(); + } + protected Repository getRepository() throws RepositoryException { if (repository == null) { - nodeStore = createNodeStore(fixture); + + if (reuseNodeStore) { + // see if there is an existing NodeStore from a previous test + nodeStore = NODE_STORES.get(fixture); + if (nodeStore == null) { + nodeStore = createNodeStore(fixture); + } + NODE_STORES.put(fixture, nodeStore); + } else { + // always create a new NodeStore (default behavior) + nodeStore = createNodeStore(fixture); + } + repository = createRepository(nodeStore); } return repository; @@ -115,6 +183,28 @@ public abstract class AbstractRepository return jcr.withAsyncIndexing().with(qs); } + protected NodeStore getNodeStore() { + return nodeStore; + } + + protected <T> T getNodeStoreComponent(Class<T> type) { + return getNodeStoreComponent(type.getName()); + } + + protected <T> T getNodeStoreComponent(String name) { + if (fixture instanceof ComponentHolder) { + return ((ComponentHolder) fixture).get(nodeStore, name); + } + return null; + } + + protected Session getAnonymousSession() throws RepositoryException { + if (anonymousSession == null) { + anonymousSession = createAnonymousSession(); + } + return anonymousSession; + } + protected Session getAdminSession() throws RepositoryException { if (adminSession == null) { adminSession = createAdminSession(); Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/AbstractBinaryAccessIT.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/AbstractBinaryAccessIT.java?rev=1838617&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/AbstractBinaryAccessIT.java (added) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/AbstractBinaryAccessIT.java Wed Aug 22 08:51:41 2018 @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.jackrabbit.oak.jcr.binary; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import javax.jcr.Repository; + +import org.apache.jackrabbit.core.data.DataStore; +import org.apache.jackrabbit.oak.api.blob.BlobAccessProvider; +import org.apache.jackrabbit.oak.fixture.NodeStoreFixture; +import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest; +import org.apache.jackrabbit.oak.jcr.Jcr; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.datastore.AzureDataStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.datastore.S3DataStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.nodestore.DocumentMemoryNodeStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.nodestore.SegmentMemoryNodeStoreFixture; +import org.apache.jackrabbit.oak.plugins.blob.datastore.directaccess.ConfigurableDataRecordAccessProvider; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.state.NodeStore; +import org.apache.jackrabbit.oak.spi.whiteboard.DefaultWhiteboard; +import org.apache.jackrabbit.oak.spi.whiteboard.Whiteboard; +import org.junit.runners.Parameterized; + +/** Base test class for testing direct HTTP access to binaries. */ +public abstract class AbstractBinaryAccessIT extends AbstractRepositoryTest { + + @Parameterized.Parameters(name = "{0}") + public static Iterable<?> dataStoreFixtures() { + Collection<NodeStoreFixture> fixtures = new ArrayList<>(); + + S3DataStoreFixture s3 = new S3DataStoreFixture(); + fixtures.add(new SegmentMemoryNodeStoreFixture(s3)); + fixtures.add(new DocumentMemoryNodeStoreFixture(s3)); + + AzureDataStoreFixture azure = new AzureDataStoreFixture(); + fixtures.add(new SegmentMemoryNodeStoreFixture(azure)); + fixtures.add(new DocumentMemoryNodeStoreFixture(azure)); + + return fixtures; + } + + protected AbstractBinaryAccessIT(NodeStoreFixture fixture, boolean reuseNodeStore) { + super(fixture, reuseNodeStore); + } + + /** + * Adjust JCR repository creation to register BlobAccessProvider (BlobStore) in Whiteboard + * so it can be picked up by oak-jcr. + */ + @Override + protected Repository createRepository(NodeStore nodeStore) { + Whiteboard wb = new DefaultWhiteboard(); + + BlobStore blobStore = getNodeStoreComponent(BlobStore.class); + if (blobStore != null && blobStore instanceof BlobAccessProvider) { + wb.register(BlobAccessProvider.class, (BlobAccessProvider) blobStore, + Collections.emptyMap()); + + } + + return initJcr(new Jcr(nodeStore).with(wb)).createRepository(); + } + + /** Return underlying DataStore configuration extension */ + protected ConfigurableDataRecordAccessProvider getConfigurableHttpDataRecordProvider() { + DataStore dataStore = getNodeStoreComponent(DataStore.class); + if (dataStore != null && dataStore instanceof ConfigurableDataRecordAccessProvider) { + return (ConfigurableDataRecordAccessProvider) dataStore; + } + throw new AssertionError("issue with test setup, cannot retrieve underlying DataStore / ConfigurableDataRecordAccessProvider"); + } +} Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/AbstractBinaryAccessIT.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessDSGCIT.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessDSGCIT.java?rev=1838617&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessDSGCIT.java (added) +++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessDSGCIT.java Wed Aug 22 08:51:41 2018 @@ -0,0 +1,290 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to You under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.jcr.binary; + +import static org.apache.jackrabbit.oak.jcr.binary.util.BinaryAccessTestUtils.getBinary; +import static org.apache.jackrabbit.oak.jcr.binary.util.BinaryAccessTestUtils.httpGet; +import static org.apache.jackrabbit.oak.jcr.binary.util.BinaryAccessTestUtils.isSuccessfulHttpPut; +import static org.apache.jackrabbit.oak.jcr.binary.util.BinaryAccessTestUtils.putBinary; +import static org.apache.jackrabbit.oak.jcr.binary.util.BinaryAccessTestUtils.storeBinaryAndRetrieve; +import static org.apache.jackrabbit.oak.plugins.blob.datastore.SharedDataStoreUtils.SharedStoreRecordType.REPOSITORY; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import javax.jcr.Binary; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.apache.jackrabbit.api.JackrabbitValueFactory; +import org.apache.jackrabbit.api.binary.BinaryDownload; +import org.apache.jackrabbit.api.binary.BinaryDownloadOptions; +import org.apache.jackrabbit.api.binary.BinaryUpload; +import org.apache.jackrabbit.core.data.DataStoreException; +import org.apache.jackrabbit.oak.fixture.NodeStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.datastore.AzureDataStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.datastore.S3DataStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.fixtures.nodestore.SegmentMemoryNodeStoreFixture; +import org.apache.jackrabbit.oak.jcr.binary.util.Content; +import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector; +import org.apache.jackrabbit.oak.plugins.blob.datastore.DataStoreBlobStore; +import org.apache.jackrabbit.oak.segment.SegmentBlobReferenceRetriever; +import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions; +import org.apache.jackrabbit.oak.segment.file.FileStore; +import org.apache.jackrabbit.oak.spi.blob.BlobStore; +import org.apache.jackrabbit.oak.spi.blob.GarbageCollectableBlobStore; +import org.apache.jackrabbit.oak.spi.cluster.ClusterRepositoryInfo; +import org.junit.Before; +import org.junit.Test; +import org.junit.runners.Parameterized; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; + +public class BinaryAccessDSGCIT extends AbstractBinaryAccessIT { + private static final String TEST_ROOT = "testroot"; + private static final long BINARY_SIZE = 1024*1024; + + private static final String TRADITIONAL_UPLOAD_1 = "tu1"; + private static final String TRADITIONAL_UPLOAD_2 = "tu2"; + private static final String DIRECT_UPLOAD_1 = "du1"; + private static final String DIRECT_UPLOAD_2 = "du2"; + + @Parameterized.Parameters(name = "{0}") + public static Iterable<?> dataStoreFixtures() { + Collection<NodeStoreFixture> fixtures = new ArrayList<>(); + fixtures.add(new SegmentMemoryNodeStoreFixture(new S3DataStoreFixture())); + fixtures.add(new SegmentMemoryNodeStoreFixture(new AzureDataStoreFixture())); + return fixtures; + } + + public BinaryAccessDSGCIT(NodeStoreFixture fixture) { + // reuse NodeStore (and DataStore) across all tests in this class + super(fixture, true); + } + + private Session session; + private JackrabbitValueFactory directUploader; + + private MarkSweepGarbageCollector garbageCollector = null; + private ThreadPoolExecutor executor = null; + + @Before + public void setup() throws RepositoryException { + session = getAdminSession(); + directUploader = (JackrabbitValueFactory) session.getValueFactory(); + + if (session.getNode("/").hasNode(TEST_ROOT)) { + session.getNode("/" + TEST_ROOT).remove(); + session.save(); + } + session.getNode("/").addNode(TEST_ROOT); + + getConfigurableHttpDataRecordProvider().setDirectUploadURIExpirySeconds(60*5); + getConfigurableHttpDataRecordProvider().setDirectDownloadURIExpirySeconds(60*5); + } + + // For debugging. + private void printTree(Node root) throws RepositoryException { + printTree(root, 0); + } + + // For debugging. + private void printTree(Node root, int level) throws RepositoryException { + for (int i=0; i<level; i++) { + System.out.print(" "); + } + System.out.println(root.getName()); + + NodeIterator iter = root.getNodes(); + while (iter.hasNext()) { + printTree(iter.nextNode(), level+1); + } + } + + private String toAbsolutePath(String leaf) { + return "/" + TEST_ROOT + "/" + leaf; + } + + private Binary createDirectBinary(String path, Content content) throws RepositoryException, IOException { + BinaryUpload upload = directUploader.initiateBinaryUpload(content.size(), 1); // multi-part not needed for this + assertNotNull(upload); + + int code = content.httpPUT(upload.getUploadURIs().iterator().next()); + assertTrue(isSuccessfulHttpPut(code, getConfigurableHttpDataRecordProvider())); + + Binary binary = directUploader.completeBinaryUpload(upload.getUploadToken()); + putBinary(session, path, binary); + + return getBinary(session, path); + } + + private void verifyBinariesExistViaSession(Session session, + Map<String, Binary> binaries, + Map<String, Content> binaryContent) + throws RepositoryException, IOException { + for (Map.Entry<String, Binary> entry : binaries.entrySet()) { + Binary b = getBinary(session, toAbsolutePath(entry.getKey())); + assertEquals(b, entry.getValue()); + binaryContent.get(entry.getKey()).assertEqualsWith(b.getStream()); + } + } + + private void verifyBinariesExistDirectly(Map<String, Binary> binaries, Map<String, Content> binaryContent) + throws RepositoryException, IOException { + for (Map.Entry<String, Binary> entry : binaries.entrySet()) { + assertTrue(entry.getValue() instanceof BinaryDownload); + URI uri = ((BinaryDownload) entry.getValue()).getURI(BinaryDownloadOptions.DEFAULT); + binaryContent.get(entry.getKey()).assertEqualsWith(httpGet(uri)); + } + } + + private void verifyBinariesDoNotExistDirectly(Map<String, Binary> deletedBinaries) throws RepositoryException { + for (Map.Entry<String, Binary> entry : deletedBinaries.entrySet()) { + assertTrue(entry.getValue() instanceof BinaryDownload); + URI uri = ((BinaryDownload) entry.getValue()).getURI(BinaryDownloadOptions.DEFAULT); + assertNull(uri); + } + } + + private void compactFileStore() { + FileStore fileStore = getNodeStoreComponent(FileStore.class); + for (int i=0; i<SegmentGCOptions.defaultGCOptions().getRetainedGenerations(); i++) { + fileStore.compactFull(); + } + } + + private MarkSweepGarbageCollector getGarbageCollector() + throws DataStoreException, IOException { + DataStoreBlobStore blobStore = (DataStoreBlobStore) getNodeStoreComponent(BlobStore.class); + FileStore fileStore = getNodeStoreComponent(FileStore.class); + File fileStoreRoot = getNodeStoreComponent(FileStore.class.getName() + ":root"); + + if (null == garbageCollector) { + String repoId = ClusterRepositoryInfo.getOrCreateId(getNodeStore()); + blobStore.addMetadataRecord(new ByteArrayInputStream(new byte[0]), + REPOSITORY.getNameFromId(repoId)); + if (null == executor) { + executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10); + } + garbageCollector = new MarkSweepGarbageCollector( + new SegmentBlobReferenceRetriever(fileStore), + blobStore, + executor, + fileStoreRoot.getAbsolutePath(), + 2048, + 0, + repoId + ); + } + return garbageCollector; + } + + private int getBlobCount() throws Exception { + GarbageCollectableBlobStore ds = (GarbageCollectableBlobStore) getNodeStoreComponent(BlobStore.class); + Set<String> chunks = Sets.newHashSet(); + Iterator<String> chunkIds = ds.getAllChunkIds(0); + while (chunkIds.hasNext()) { + chunks.add(chunkIds.next()); + } + return chunks.size(); + } + + @Test + public void testGC() throws Exception { + Map<String, Content> binaryContent = Maps.newHashMap(); + Map<String, Binary> binaries = Maps.newHashMap(); + + for (String key : Lists.newArrayList(TRADITIONAL_UPLOAD_1, TRADITIONAL_UPLOAD_2)) { + Content content = Content.createRandom(BINARY_SIZE); + binaryContent.put(key, content); + binaries.put(key, storeBinaryAndRetrieve(session, toAbsolutePath(key), content)); + } + for (String key : Lists.newArrayList(DIRECT_UPLOAD_1, DIRECT_UPLOAD_2)) { + Content content = Content.createRandom(BINARY_SIZE); + binaryContent.put(key, content); + binaries.put(key, createDirectBinary(toAbsolutePath(key), content)); + } + session.save(); + + // Test that all four binaries can be accessed + assertEquals(4, getBlobCount()); + // - Download all four via repo + verifyBinariesExistViaSession(session, binaries, binaryContent); + // - Download directly + verifyBinariesExistDirectly(binaries, binaryContent); + + // Delete one of the binaries uploaded via repo and one uploaded directly + Node testRoot = session.getNode("/" + TEST_ROOT); + List<String> deletedBinaryPaths = Lists.newArrayList(TRADITIONAL_UPLOAD_2, DIRECT_UPLOAD_2); + for (String path : deletedBinaryPaths) { + Node toRemove = testRoot.getNode(path); + toRemove.remove(); + } + session.save(); + + + // Verify that they are deleted from repo + for (String path : deletedBinaryPaths) { + assertFalse(session.nodeExists(toAbsolutePath(path))); + } + + // Verify that all four binaries are still in data store + assertEquals(4, getBlobCount()); + + + // Run DSGC + compactFileStore(); + MarkSweepGarbageCollector garbageCollector = getGarbageCollector(); + garbageCollector.collectGarbage(false); + + // Verify that only two binaries remain in data store + assertEquals(2, getBlobCount()); + + // Verify that the two binaries remaining can still be accessed + Map<String, Binary> deletedBinaries = Maps.newHashMap(); + for (String deletedPath : Lists.newArrayList(TRADITIONAL_UPLOAD_2, DIRECT_UPLOAD_2)) { + deletedBinaries.put(deletedPath, binaries.get(deletedPath)); + binaries.remove(deletedPath); + binaryContent.remove(deletedPath); + } + + verifyBinariesExistViaSession(session, binaries, binaryContent); + verifyBinariesExistDirectly(binaries, binaryContent); + + verifyBinariesDoNotExistDirectly(deletedBinaries); + } +} Propchange: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/binary/BinaryAccessDSGCIT.java ------------------------------------------------------------------------------ svn:eol-style = native
