Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java (revision 1387887) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentRepositoryImpl.java (working copy) @@ -16,11 +16,13 @@ */ package org.apache.jackrabbit.oak.core; +import java.security.PrivilegedAction; import java.util.Collections; import javax.annotation.Nonnull; import javax.jcr.Credentials; import javax.jcr.NoSuchWorkspaceException; +import javax.security.auth.Subject; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; @@ -36,9 +38,11 @@ import org.apache.jackrabbit.oak.spi.commit.CompositeValidatorProvider; import org.apache.jackrabbit.oak.spi.commit.ValidatingHook; import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider; +import org.apache.jackrabbit.oak.spi.lifecycle.LifeCycleHook; import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider; import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; import org.apache.jackrabbit.oak.spi.security.authentication.LoginContextProvider; +import org.apache.jackrabbit.oak.spi.security.principal.AdminPrincipal; import org.apache.jackrabbit.oak.spi.state.NodeState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,7 +114,23 @@ */ public ContentRepositoryImpl(MicroKernel microKernel, QueryIndexProvider indexProvider, CommitHook commitHook) { + this(microKernel, indexProvider, commitHook, null); + } + /** + * Creates an Oak repository instance based on the given, already + * initialized components. + * + * @param microKernel underlying kernel instance + * @param indexProvider index provider + * @param commitHook the commit hook + * @param lifeCycleHook the life cycle hook + */ + public ContentRepositoryImpl(MicroKernel microKernel, + QueryIndexProvider indexProvider, + CommitHook commitHook, + final LifeCycleHook lifeCycleHook) { + nodeStore = new KernelNodeStore(microKernel); nodeStore.setHook(commitHook); @@ -136,6 +156,20 @@ "\"jcr:activities\" :{\"jcr:primaryType\":\"nam:rep:Activities\"}," + "\"rep:privileges\" :{\"jcr:primaryType\":\"nam:rep:Privileges\"}}", null, null); } + + if (lifeCycleHook != null) { + // TODO: use principal only visible to oak-core + final Subject admin = new Subject(); + admin.getPrincipals().add(AdminPrincipal.INSTANCE); + Subject.doAs(admin, new PrivilegedAction() { + @Override + public Void run() { + lifeCycleHook.repositoryInitialized( + new RootImpl(nodeStore, null, admin)); + return null; + } + }); + } } @Nonnull Index: oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java (revision 1387887) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/core/ContentSessionImpl.java (working copy) @@ -28,7 +28,6 @@ import org.apache.jackrabbit.oak.api.CoreValueFactory; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.api.SessionQueryEngine; -import org.apache.jackrabbit.oak.plugins.type.BuiltInNodeTypes; import org.apache.jackrabbit.oak.query.QueryEngineImpl; import org.apache.jackrabbit.oak.query.SessionQueryEngineImpl; import org.apache.jackrabbit.oak.spi.state.NodeStore; @@ -49,8 +48,6 @@ private final NodeStore store; private final SessionQueryEngine queryEngine; - private boolean initialised; - public ContentSessionImpl(LoginContext loginContext, String workspaceName, NodeStore store, QueryEngineImpl queryEngine) { @@ -74,14 +71,6 @@ @Nonnull @Override public Root getLatestRoot() { - // TODO: improve initial repository/session. See OAK-41 - synchronized (this) { - if (!initialised) { - initialised = true; - BuiltInNodeTypes.register(getLatestRoot()); - } - } - return new RootImpl(store, workspaceName, loginContext.getSubject()); } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/Activator.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/Activator.java (revision 1387887) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/Activator.java (working copy) @@ -26,9 +26,12 @@ import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.core.ContentRepositoryImpl; import org.apache.jackrabbit.oak.plugins.type.DefaultTypeEditor; +import org.apache.jackrabbit.oak.plugins.type.TypeLifeCycleHook; import org.apache.jackrabbit.oak.spi.commit.CommitHook; import org.apache.jackrabbit.oak.spi.commit.CompositeHook; import org.apache.jackrabbit.oak.spi.commit.ValidatingHook; +import org.apache.jackrabbit.oak.spi.lifecycle.CompositeLifeCycleHook; +import org.apache.jackrabbit.oak.spi.lifecycle.LifeCycleHook; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; @@ -82,11 +85,16 @@ hooks.add(new ValidatingHook(validatorProvider)); // hooks.add(new LuceneEditor()); + // TODO: introduce LifeCycleHookProvider? + LifeCycleHook lifeCycleHook = new CompositeLifeCycleHook( + new TypeLifeCycleHook()); + MicroKernel kernel = (MicroKernel) service; services.put(reference, context.registerService( ContentRepository.class.getName(), new ContentRepositoryImpl( - kernel, indexProvider, new CompositeHook(hooks)), + kernel, indexProvider, new CompositeHook(hooks), + lifeCycleHook), new Properties())); return service; } else { Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/type/BuiltInNodeTypes.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/type/BuiltInNodeTypes.java (revision 1387887) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/type/BuiltInNodeTypes.java (working copy) @@ -18,14 +18,11 @@ import java.io.InputStream; import java.io.InputStreamReader; -import java.security.PrivilegedAction; import javax.annotation.Nonnull; -import javax.security.auth.Subject; import org.apache.jackrabbit.oak.api.Root; import org.apache.jackrabbit.oak.api.Tree; -import org.apache.jackrabbit.oak.spi.security.principal.AdminPrincipal; import static org.apache.jackrabbit.oak.plugins.type.NodeTypeConstants.NODE_TYPES_PATH; @@ -68,25 +65,17 @@ // not have sufficient permission to register node types or may // even have limited read-permission on the jcr:nodetypes path. if (!nodeTypesInContent()) { - Subject admin = new Subject(); - admin.getPrincipals().add(AdminPrincipal.INSTANCE); - Subject.doAs(admin, new PrivilegedAction() { - @Override - public Void run() { - try { - InputStream stream = BuiltInNodeTypes.class.getResourceAsStream("builtin_nodetypes.cnd"); - try { - ntMgr.registerNodeTypes(new InputStreamReader(stream, "UTF-8")); - } finally { - stream.close(); - } - } catch (Exception e) { - throw new IllegalStateException( - "Unable to load built-in node types", e); - } - return null; + try { + InputStream stream = BuiltInNodeTypes.class.getResourceAsStream("builtin_nodetypes.cnd"); + try { + ntMgr.registerNodeTypes(new InputStreamReader(stream, "UTF-8")); + } finally { + stream.close(); } - }); + } catch (Exception e) { + throw new IllegalStateException( + "Unable to load built-in node types", e); + } } } Index: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/type/TypeLifeCycleHook.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/type/TypeLifeCycleHook.java (revision 0) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/type/TypeLifeCycleHook.java (revision 0) @@ -0,0 +1,33 @@ +/* + * 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.plugins.type; + +import org.apache.jackrabbit.oak.api.Root; +import org.apache.jackrabbit.oak.spi.lifecycle.DefaultLifeCycleHook; +import org.apache.jackrabbit.oak.spi.lifecycle.LifeCycleHook; + +/** + * TypeLifeCycleHook implements a {@link LifeCycleHook} and + * registers built-in node types on repository initialization. + */ +public class TypeLifeCycleHook extends DefaultLifeCycleHook { + + @Override + public void repositoryInitialized(Root root) { + BuiltInNodeTypes.register(root); + } +} Property changes on: oak-core\src\main\java\org\apache\jackrabbit\oak\plugins\type\TypeLifeCycleHook.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/CompositeLifeCycleHook.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/CompositeLifeCycleHook.java (revision 0) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/CompositeLifeCycleHook.java (revision 0) @@ -0,0 +1,49 @@ +/* + * 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.spi.lifecycle; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.apache.jackrabbit.oak.api.Root; + +/** + * CompositeLifeCycleHook... + */ +public class CompositeLifeCycleHook implements LifeCycleHook { + + private final List hooks = new ArrayList(); + + public CompositeLifeCycleHook(Collection hooks) { + this.hooks.addAll(hooks); + } + + public CompositeLifeCycleHook(LifeCycleHook... hooks) { + this.hooks.addAll(Arrays.asList(hooks)); + } + + @Override + public void repositoryInitialized(Root root) { + for (LifeCycleHook hook : hooks) { + hook.repositoryInitialized(root); + } + } +} Property changes on: oak-core\src\main\java\org\apache\jackrabbit\oak\spi\lifecycle\CompositeLifeCycleHook.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/DefaultLifeCycleHook.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/DefaultLifeCycleHook.java (revision 0) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/DefaultLifeCycleHook.java (revision 0) @@ -0,0 +1,36 @@ +/* + * 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.spi.lifecycle; + +import org.apache.jackrabbit.oak.api.Root; + +/** + * DefaultLifeCycleHook is a default implementation of all methods + * specified in {@link LifeCycleHook}. The methods immediately return and do + * nothing. + *

+ * This class can be used when a hook only wants to get callbacks for some of + * the life cycle events and does not want to implement all methods specified + * in {@link LifeCycleHook}. This also guarantees forward compatibility when + * new methods are introduced in later versions. + */ +public class DefaultLifeCycleHook implements LifeCycleHook { + + @Override + public void repositoryInitialized(Root root) { + } +} Property changes on: oak-core\src\main\java\org\apache\jackrabbit\oak\spi\lifecycle\DefaultLifeCycleHook.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native Index: oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/LifeCycleHook.java =================================================================== --- oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/LifeCycleHook.java (revision 0) +++ oak-core/src/main/java/org/apache/jackrabbit/oak/spi/lifecycle/LifeCycleHook.java (revision 0) @@ -0,0 +1,31 @@ +/* + * 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.spi.lifecycle; + +import org.apache.jackrabbit.oak.api.Root; + +/** + * LifeCycleHook... + * + * TODO: introduce methods related to workspace life cycle? + */ +public interface LifeCycleHook { + + public void repositoryInitialized(Root root); +} Property changes on: oak-core\src\main\java\org\apache\jackrabbit\oak\spi\lifecycle\LifeCycleHook.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Rev URL Added: svn:eol-style + native Index: oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractOakTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractOakTest.java (revision 1387887) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractOakTest.java (working copy) @@ -16,6 +16,9 @@ */ package org.apache.jackrabbit.oak; +import java.util.ArrayList; +import java.util.List; + import javax.jcr.Credentials; import javax.jcr.GuestCredentials; import javax.jcr.NoSuchWorkspaceException; @@ -25,6 +28,9 @@ import org.apache.jackrabbit.oak.api.ContentRepository; import org.apache.jackrabbit.oak.api.ContentSession; import org.apache.jackrabbit.oak.core.ContentRepositoryImpl; +import org.apache.jackrabbit.oak.plugins.type.TypeLifeCycleHook; +import org.apache.jackrabbit.oak.spi.lifecycle.CompositeLifeCycleHook; +import org.apache.jackrabbit.oak.spi.lifecycle.LifeCycleHook; import org.junit.Before; /** @@ -62,4 +68,10 @@ return new SimpleCredentials("admin", "admin".toCharArray()); } + protected static LifeCycleHook createDefaultLifeCycleHook() { + List hooks = new ArrayList(); + hooks.add(new TypeLifeCycleHook()); + return new CompositeLifeCycleHook(hooks); + } + } \ No newline at end of file Index: oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java (revision 1387887) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/lucene/AbstractLuceneQueryTest.java (working copy) @@ -35,6 +35,7 @@ import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider; import org.apache.jackrabbit.oak.plugins.name.NamespaceValidatorProvider; import org.apache.jackrabbit.oak.plugins.type.DefaultTypeEditor; +import org.apache.jackrabbit.oak.plugins.type.TypeLifeCycleHook; import org.apache.jackrabbit.oak.plugins.type.TypeValidatorProvider; import org.apache.jackrabbit.oak.plugins.value.ConflictValidatorProvider; import org.apache.jackrabbit.oak.spi.commit.CommitHook; @@ -42,6 +43,8 @@ import org.apache.jackrabbit.oak.spi.commit.CompositeValidatorProvider; import org.apache.jackrabbit.oak.spi.commit.ValidatingHook; import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider; +import org.apache.jackrabbit.oak.spi.lifecycle.CompositeLifeCycleHook; +import org.apache.jackrabbit.oak.spi.lifecycle.LifeCycleHook; import org.apache.jackrabbit.oak.spi.query.CompositeQueryIndexProvider; import org.apache.jackrabbit.oak.spi.query.QueryIndexProvider; import org.junit.Before; @@ -75,7 +78,8 @@ mk = new MicroKernelImpl(); QueryIndexProvider indexer = new LuceneIndexProvider(DEFAULT_INDEX_HOME); QueryIndexProvider qip = new CompositeQueryIndexProvider(indexer); - return new ContentRepositoryImpl(mk, qip, buildDefaultCommitHook()); + return new ContentRepositoryImpl(mk, qip, buildDefaultCommitHook(), + createDefaultLifeCycleHook()); } private CommitHook buildDefaultCommitHook() { Index: oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java =================================================================== --- oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java (revision 1387887) +++ oak-core/src/test/java/org/apache/jackrabbit/oak/query/AbstractQueryTest.java (working copy) @@ -55,7 +55,8 @@ PropertyIndexer pi = new PropertyIndexer(indexer); QueryIndexProvider qip = new CompositeQueryIndexProvider(pi); CompositeHook hook = new CompositeHook(pi); - return new ContentRepositoryImpl(mk, qip, hook); + return new ContentRepositoryImpl(mk, qip, hook, + createDefaultLifeCycleHook()); } @Override Index: oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java =================================================================== --- oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java (revision 1387887) +++ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/RepositoryImpl.java (working copy) @@ -34,6 +34,7 @@ import org.apache.jackrabbit.oak.core.ContentRepositoryImpl; import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider; import org.apache.jackrabbit.oak.plugins.name.NamespaceValidatorProvider; +import org.apache.jackrabbit.oak.plugins.type.TypeLifeCycleHook; import org.apache.jackrabbit.oak.plugins.type.TypeValidatorProvider; import org.apache.jackrabbit.oak.plugins.unique.UniqueIndexHook; import org.apache.jackrabbit.oak.plugins.value.ConflictValidatorProvider; @@ -45,6 +46,8 @@ import org.apache.jackrabbit.oak.spi.commit.CompositeValidatorProvider; import org.apache.jackrabbit.oak.spi.commit.ValidatingHook; import org.apache.jackrabbit.oak.spi.commit.ValidatorProvider; +import org.apache.jackrabbit.oak.spi.lifecycle.CompositeLifeCycleHook; +import org.apache.jackrabbit.oak.spi.lifecycle.LifeCycleHook; import org.apache.jackrabbit.oak.spi.security.user.UserConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -71,6 +74,10 @@ new UserValidatorProvider(new UserConfig("admin")), new PrivilegeValidatorProvider()); + private static final LifeCycleHook DEFAULT_LIFE_CYCLE_HOOK = + new CompositeLifeCycleHook( + new TypeLifeCycleHook()); + private final Descriptors descriptors = new Descriptors(new SimpleValueFactory()); private final ContentRepository contentRepository; @@ -88,7 +95,7 @@ this(new ContentRepositoryImpl( kernel, null, new CompositeHook( new ValidatingHook(DEFAULT_VALIDATOR), - new UniqueIndexHook())), + new UniqueIndexHook()), DEFAULT_LIFE_CYCLE_HOOK), executor); }