001/*
002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the Eclipse Public License v1.0
006 * which accompanies this distribution, and is available at
007 * http://www.eclipse.org/legal/epl-v10.html
008 *
009 * Contributors:
010 *     bstefanescu
011 *
012 * $Id$
013 */
014
015package org.nuxeo.ecm.core.repository;
016
017import org.nuxeo.ecm.core.api.CoreSession;
018
019/**
020 * A repository initialization handler is responsible for initializing a repository content.
021 * <p>
022 * The handler is called each time a repository is opened in a JVM session. This can be used to create a default
023 * structure for the repository.
024 * <p>
025 * To register a repository initializer <code>MyInitHandler</code> you should do:
026 * <p>
027 * <code>RepositoryInitializationHandler.setInstance(new MyInitHandler());</code>
028 * <p>
029 * If you want to create an initialization chain you can implement to delegate to the parent handle the default
030 * initialization and then to do your specific initialization stuff
031 * <p>
032 *
033 * <pre>
034 * <code>
035 * RepositoryInitializationHandler parentHandler = RepositoryInitializationHandler.getInstance();
036 * MyInitHandler myHandler = new MyInitHandler(parentHandler);
037 * RepositoryInitializationHandler.setInstance(myHandler);
038 * ...
039 * class MyHandler extends RepositoryInitializationHandler {
040 *      ...
041 *      public initializeRepository(CoreSession session) {
042 *        if (parentHandler != null) parentHandler.initializeRepository(session);
043 *        // do my own initialization here
044 *        ...
045 *      }
046 *      ...
047 * }
048 * </code>
049 * </pre>
050 * <p>
051 * <b>Important Note:</b> Use the given session to initialize the repository. Do not create other repository sessions
052 * when initializing the repository to avoid dead locks.
053 *
054 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
055 */
056public abstract class RepositoryInitializationHandler {
057
058    private static RepositoryInitializationHandler instance;
059
060    public static RepositoryInitializationHandler getInstance() {
061        return instance;
062    }
063
064    /**
065     * The parent handler if any otherwise null
066     */
067    protected RepositoryInitializationHandler previous;
068
069    /**
070     * The next handler in the chain if any or null otherwise
071     */
072    protected RepositoryInitializationHandler next;
073
074    public abstract void doInitializeRepository(CoreSession session);
075
076    /**
077     * Must be implemented by custom initializers.
078     *
079     * @param session the current session
080     */
081    public void initializeRepository(CoreSession session) {
082        synchronized (RepositoryInitializationHandler.class) {
083            if (previous != null) {
084                previous.initializeRepository(session);
085            }
086            doInitializeRepository(session);
087        }
088    }
089
090    public void install() {
091        synchronized (RepositoryInitializationHandler.class) {
092            previous = instance;
093            if (previous != null) {
094                previous.next = this;
095            }
096            instance = this;
097        }
098    }
099
100    public void uninstall() {
101        synchronized (RepositoryInitializationHandler.class) {
102            if (previous != null) {
103                previous.next = next;
104            }
105            if (next != null) {
106                next.previous = previous;
107            }
108            if (instance == this) {
109                instance = previous;
110            }
111        }
112    }
113
114    public RepositoryInitializationHandler getPrevious() {
115        return previous;
116    }
117
118    public RepositoryInitializationHandler getNext() {
119        return next;
120    }
121
122}