001/*
002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 *
019 * $Id$
020 */
021
022package org.nuxeo.ecm.core.repository;
023
024import org.nuxeo.ecm.core.api.CoreSession;
025
026/**
027 * A repository initialization handler is responsible for initializing a repository content.
028 * <p>
029 * The handler is called each time a repository is opened in a JVM session. This can be used to create a default
030 * structure for the repository.
031 * <p>
032 * To register a repository initializer <code>MyInitHandler</code> you should do:
033 * <p>
034 * <code>RepositoryInitializationHandler.setInstance(new MyInitHandler());</code>
035 * <p>
036 * If you want to create an initialization chain you can implement to delegate to the parent handle the default
037 * initialization and then to do your specific initialization stuff
038 * <p>
039 *
040 * <pre>
041 * <code>
042 * RepositoryInitializationHandler parentHandler = RepositoryInitializationHandler.getInstance();
043 * MyInitHandler myHandler = new MyInitHandler(parentHandler);
044 * RepositoryInitializationHandler.setInstance(myHandler);
045 * ...
046 * class MyHandler extends RepositoryInitializationHandler {
047 *      ...
048 *      public initializeRepository(CoreSession session) {
049 *        if (parentHandler != null) parentHandler.initializeRepository(session);
050 *        // do my own initialization here
051 *        ...
052 *      }
053 *      ...
054 * }
055 * </code>
056 * </pre>
057 * <p>
058 * <b>Important Note:</b> Use the given session to initialize the repository. Do not create other repository sessions
059 * when initializing the repository to avoid dead locks.
060 *
061 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
062 */
063public abstract class RepositoryInitializationHandler {
064
065    private static RepositoryInitializationHandler instance;
066
067    public static RepositoryInitializationHandler getInstance() {
068        return instance;
069    }
070
071    /**
072     * The parent handler if any otherwise null
073     */
074    protected RepositoryInitializationHandler previous;
075
076    /**
077     * The next handler in the chain if any or null otherwise
078     */
079    protected RepositoryInitializationHandler next;
080
081    public abstract void doInitializeRepository(CoreSession session);
082
083    /**
084     * Must be implemented by custom initializers.
085     *
086     * @param session the current session
087     */
088    public void initializeRepository(CoreSession session) {
089        synchronized (RepositoryInitializationHandler.class) {
090            if (previous != null) {
091                previous.initializeRepository(session);
092            }
093            doInitializeRepository(session);
094        }
095    }
096
097    public void install() {
098        synchronized (RepositoryInitializationHandler.class) {
099            previous = instance;
100            if (previous != null) {
101                previous.next = this;
102            }
103            instance = this;
104        }
105    }
106
107    public void uninstall() {
108        synchronized (RepositoryInitializationHandler.class) {
109            if (previous != null) {
110                previous.next = next;
111            }
112            if (next != null) {
113                next.previous = previous;
114            }
115            if (instance == this) {
116                instance = previous;
117            }
118        }
119    }
120
121    public RepositoryInitializationHandler getPrevious() {
122        return previous;
123    }
124
125    public RepositoryInitializationHandler getNext() {
126        return next;
127    }
128
129}