/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Nuxeo - initial API and implementation * * $Id$ */ package org.eclipse.ecr.core.api; import java.io.Serializable; import java.util.Collection; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.ecr.core.api.impl.DocumentModelImpl; import org.eclipse.ecr.core.api.repository.Repository; import org.eclipse.ecr.core.api.repository.RepositoryManager; import org.eclipse.ecr.core.schema.DocumentType; import org.eclipse.ecr.runtime.api.Framework; /** * The CoreInstance is the main access point to a repository server. * <p> * A server instance is a singleton object that exists on each client JVM but * also on the server JVM. The instance on the server JVM is used to access the * server locally while those on client JVMs are used to access the server * remotely. * <p> * A server instance uses a CoreSessionFactory to create CoreSession instances. * CoreSessionFactory objects are implementation-dependent and may be registered * using extension points. See {@link CoreSessionFactory} for more details. * <p> * Thus you can use a different implementation for the local ServerConnector * than the one for the remote ServerConnector. * <p> * When clients need to perform a connection to a repository, they simply open a * new session using the {@link CoreInstance#open(String, Map)} method. * <p> * When the client has done its work it <b>must</b> close its session by calling * {@link CoreInstance#close(CoreSession)}. * <p> * This ensures correctly freeing all the resources held by the client session. * <p> * So a client session looks something like this: * <p> * * <pre> * <code> * CoreInstance server = CoreInstance.getInstance(); * CoreSession client = server.open("demo", null); * DocumentModel root = client.getRootDocument(); * // ... do something in that session ... * // close the client -> this is closing the core session * server.close(client); * </code> * </pre> * * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> */ public class CoreInstance implements Serializable { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(CoreInstance.class); private static final CoreInstance instance = new CoreInstance(); private CoreSessionFactory factory; private final Map<String, CoreSession> sessions = new ConcurrentHashMap<String, CoreSession>(); private final Map<String, DocumentType> docTypes = new Hashtable<String, DocumentType>(); // hiding the default constructor from clients protected CoreInstance() { } /** * Gets the CoreInstance singleton. * * @return the server instance */ public static CoreInstance getInstance() { return instance; } public DocumentType getCachedDocumentType(String type) { return docTypes.get(type); } public void cacheDocumentType(DocumentType docType) { docTypes.put(docType.getName(), docType); } public CoreSession open(String repositoryName, Map<String, Serializable> context) throws ClientException { // instantiate a new client try { RepositoryManager rm = Framework.getService(RepositoryManager.class); CoreSession session = null; if (rm != null) { Repository repo = rm.getRepository(repositoryName); if (repo == null) { throw new ClientException("No such repository: " + repositoryName); } // connect to the server session = repo.open(context); } // ------ FIXME only for compat with tests --- if (session == null) { session = compatOpen(repositoryName, context); } // -------------------------------------------------------- return session; } catch (Exception e) { throw new ClientException( "Failed to intialize core session on repository " + repositoryName, e); } } /** * Obsolete method only for compatibility with existing tests. Should be * removed. * * @deprecated remove it */ @Deprecated private CoreSession compatOpen(String repositoryName, Map<String, Serializable> context) throws ClientException { // instantiate a new client CoreSession client = factory.getSession(); // connect to the server client.connect(repositoryName, context); // register the client locally sessions.put(client.getSessionId(), client); return client; } public void registerSession(String sid, CoreSession session) { sessions.put(sid, session); } public CoreSession unregisterSession(String sid) { return sessions.remove(sid); } public void close(CoreSession client) { String sid = client.getSessionId(); if (sid == null) { return; // session not yet connected } client = sessions.remove(sid); if (client != null) { client.destroy(); } else { log.warn("Trying to close a non referenced CoreSession (destroy method won't be called)"); } } public boolean isSessionStarted(String sid) { return sessions.containsKey(sid); } /** @deprecated unused */ @Deprecated public CoreSession[] getSessions() { Collection<CoreSession> valuesOfMap = sessions.values(); return valuesOfMap.toArray(new CoreSession[0]); } /** * Gets the client bound to the given session. * * @param sid the session id * @return the client */ public CoreSession getSession(String sid) { HashMap<String, CoreSession> reentrantSession = DocumentModelImpl.reentrantCoreSession.get(); if (reentrantSession!=null && reentrantSession.containsKey(sid)) { return reentrantSession.get(sid); } return sessions.get(sid); } public void initialize(CoreSessionFactory factory) { // TODO: to be able to test more easily with a variety of client // factories // if (instance.factory == null) { instance.factory = factory; // } } public CoreSessionFactory getFactory() { return factory; } }