/* * 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: * Florent Guillaume */ package org.eclipse.ecr.core.storage.sql.ra; import java.io.Serializable; import java.util.Collection; import java.util.Map; import javax.naming.Reference; import javax.resource.ResourceException; import javax.resource.cci.ConnectionSpec; import javax.resource.cci.RecordFactory; import javax.resource.cci.ResourceAdapterMetaData; import javax.resource.spi.ConnectionManager; import javax.resource.spi.ConnectionRequestInfo; import org.eclipse.ecr.core.api.DocumentException; import org.eclipse.ecr.core.api.NuxeoPrincipal; import org.eclipse.ecr.core.repository.RepositoryDescriptor; import org.eclipse.ecr.core.repository.RepositoryService; import org.eclipse.ecr.core.schema.SchemaManager; import org.eclipse.ecr.core.security.SecurityManager; import org.eclipse.ecr.core.storage.Credentials; import org.eclipse.ecr.core.storage.StorageException; import org.eclipse.ecr.core.storage.sql.ConnectionSpecImpl; import org.eclipse.ecr.core.storage.sql.Repository; import org.eclipse.ecr.core.storage.sql.Session; import org.eclipse.ecr.core.storage.sql.coremodel.SQLRepository; import org.eclipse.ecr.core.storage.sql.coremodel.SQLSecurityManager; import org.eclipse.ecr.core.storage.sql.coremodel.SQLSession; import org.eclipse.ecr.core.storage.sql.net.MapperClientInfo; import org.eclipse.ecr.runtime.api.Framework; /** * The connection factory delegates connection requests to the application * server {@link ConnectionManager}. * <p> * An instance of this class is returned to the application when a JNDI lookup * is done. This is the datasource equivalent of {@link SQLRepository}. * * @author Florent Guillaume */ public class ConnectionFactoryImpl implements Repository, org.eclipse.ecr.core.model.Repository { private static final long serialVersionUID = 1L; private final ManagedConnectionFactoryImpl managedConnectionFactory; private final ConnectionManager connectionManager; private final String name; private SecurityManager securityManager; private SchemaManager schemaManager; private Reference reference; /** * This is {@code true} if the connectionManager comes from an application * server, or {@code false} if the {@link ConnectionFactoryImpl} was * constructed by application code and passed our manual * {@link ConnectionManagerImpl}. */ private final boolean managed; private boolean firstAccessInitialized; private boolean servicesInitialized; public ConnectionFactoryImpl( ManagedConnectionFactoryImpl managedConnectionFactory, ConnectionManager connectionManager) { this.managedConnectionFactory = managedConnectionFactory; this.connectionManager = connectionManager; managed = !(connectionManager instanceof ConnectionManagerImpl); name = managedConnectionFactory.getName(); } // NXP 3992 -- exposed this for clean shutdown on cluster public ManagedConnectionFactoryImpl getManagedConnectionFactory() { return managedConnectionFactory; } protected void initializeServices() { if (!servicesInitialized) { servicesInitialized = true; /* * Look up the configuration for this repository. */ try { RepositoryService repositoryService = Framework.getService(RepositoryService.class); if (repositoryService != null) { RepositoryDescriptor descriptor = repositoryService.getRepositoryManager().getDescriptor( name); if (descriptor.getSecurityManagerClass() != null) { securityManager = descriptor.getSecurityManager(); } } if (securityManager == null) { securityManager = new SQLSecurityManager(); } schemaManager = Framework.getService(SchemaManager.class); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } } /* * ----- javax.resource.cci.ConnectionFactory ----- */ /** * Gets a new connection, with no credentials. * * @return the connection */ @Override public Session getConnection() throws StorageException { ConnectionRequestInfo connectionRequestInfo = new ConnectionRequestInfoImpl(); try { return (Session) connectionManager.allocateConnection( managedConnectionFactory, connectionRequestInfo); } catch (StorageException e) { throw e; } catch (ResourceException e) { throw new StorageException(e); } } /** * Gets a new connection. * * @param connectionSpec the connection spec, containing credentials * @return the connection */ @Override public Session getConnection(ConnectionSpec connectionSpec) throws StorageException { assert connectionSpec instanceof ConnectionSpecImpl; // encapsulate connectionSpec into internal connectionRequestInfo ConnectionRequestInfo connectionRequestInfo = new ConnectionRequestInfoImpl( (ConnectionSpecImpl) connectionSpec); try { return (Session) connectionManager.allocateConnection( managedConnectionFactory, connectionRequestInfo); } catch (StorageException e) { throw e; } catch (ResourceException e) { throw new StorageException(e); } } @Override public ResourceAdapterMetaData getMetaData() throws ResourceException { // TODO Auto-generated method stub throw new UnsupportedOperationException("Not implemented"); } @Override public RecordFactory getRecordFactory() throws ResourceException { throw new UnsupportedOperationException("Not implemented"); } /* * ----- javax.naming.Referenceable ----- */ @Override public Reference getReference() { return reference; } @Override public void setReference(Reference reference) { this.reference = reference; } /* * ----- Repository ----- */ @Override public void close() throws StorageException { throw new UnsupportedOperationException("Not implemented"); } /* * ----- org.eclipse.ecr.core.model.Repository ----- */ @Override public String getName() { return name; } @Override public org.eclipse.ecr.core.model.Session getSession( Map<String, Serializable> context) throws DocumentException { ConnectionSpec connectionSpec; if (context == null) { connectionSpec = null; } else { synchronized (this) { if (!firstAccessInitialized) { firstAccessInitialized = true; // Allow AbstractSession (our caller) to send an // initialization event. context.put("REPOSITORY_FIRST_ACCESS", Boolean.TRUE); } } NuxeoPrincipal principal = (NuxeoPrincipal) context.get("principal"); String username = principal == null ? (String) context.get("username") : principal.getName(); connectionSpec = new ConnectionSpecImpl(new Credentials(username, null)); } Session session; try { session = getConnection(connectionSpec); } catch (StorageException e) { throw new DocumentException(e); } return new SQLSession(session, this, context); } /** * @deprecated unused */ @Override @Deprecated public org.eclipse.ecr.core.model.Session getSession(long sessionId) throws DocumentException { throw new UnsupportedOperationException("unused"); } @Override public SecurityManager getNuxeoSecurityManager() { initializeServices(); return securityManager; } @Override public SchemaManager getTypeManager() { initializeServices(); return schemaManager; } /* * Used only by unit tests. Shouldn't be in public API. */ @Override public void initialize() { } /* * Used only by core MBean. */ @Override public synchronized org.eclipse.ecr.core.model.Session[] getOpenedSessions() { return new org.eclipse.ecr.core.model.Session[0]; } @Override public void shutdown() { managedConnectionFactory.shutdown(); } @Override public int getStartedSessionsCount() { return 0; } @Override public int getClosedSessionsCount() { return 0; } /* * ----- org.eclipse.ecr.core.model.RepositoryManagement ----- */ @Override public int getActiveSessionsCount() { return managedConnectionFactory.getActiveSessionsCount(); } @Override public int clearCaches() { return managedConnectionFactory.clearCaches(); } @Override public void processClusterInvalidationsNext() { managedConnectionFactory.processClusterInvalidationsNext(); } @Override public boolean supportsTags() { return true; } @Override public void activateServer() { managedConnectionFactory.activateServer(); } @Override public void deactivateServer() { managedConnectionFactory.deactivateServer(); } @Override public Collection<MapperClientInfo> getClientInfos() { return managedConnectionFactory.getClientInfos(); } @Override public boolean isServerActivated() { return managedConnectionFactory.isServerActivated(); } @Override public String getServerURL() { return managedConnectionFactory.getServerURL(); } }