blob: 4cca73d5e9d064bf700059eff8328e4843728203 [file] [log] [blame]
/***************************************************************************
* Copyright (c) 2004 - 2008 Eike Stepper, Germany.
* 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:
* Eike Stepper - initial API and implementation
* Simon McDuff - http://bugs.eclipse.org/226778
* Simon McDuff - http://bugs.eclipse.org/230832
* Simon McDuff - http://bugs.eclipse.org/233490
* Simon McDuff - http://bugs.eclipse.org/213402
**************************************************************************/
package org.eclipse.emf.internal.cdo;
import org.eclipse.emf.cdo.CDOAudit;
import org.eclipse.emf.cdo.CDOCollectionLoadingPolicy;
import org.eclipse.emf.cdo.CDOSession;
import org.eclipse.emf.cdo.CDOSessionInvalidationEvent;
import org.eclipse.emf.cdo.CDOTimestampContext;
import org.eclipse.emf.cdo.CDOView;
import org.eclipse.emf.cdo.CDOViewSet;
import org.eclipse.emf.cdo.common.CDOProtocolConstants;
import org.eclipse.emf.cdo.common.CDOProtocolView;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.id.CDOIDAndVersion;
import org.eclipse.emf.cdo.common.id.CDOIDLibraryDescriptor;
import org.eclipse.emf.cdo.common.id.CDOIDMetaRange;
import org.eclipse.emf.cdo.common.id.CDOIDObject;
import org.eclipse.emf.cdo.common.id.CDOIDObjectFactory;
import org.eclipse.emf.cdo.common.id.CDOIDTemp;
import org.eclipse.emf.cdo.common.id.CDOIDTempMeta;
import org.eclipse.emf.cdo.common.id.CDOIDUtil;
import org.eclipse.emf.cdo.common.model.CDOPackage;
import org.eclipse.emf.cdo.common.model.CDOPackageURICompressor;
import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta;
import org.eclipse.emf.cdo.spi.common.InternalCDORevision;
import org.eclipse.emf.cdo.util.CDOPackageRegistry;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.internal.cdo.bundle.OM;
import org.eclipse.emf.internal.cdo.protocol.CDOClientProtocol;
import org.eclipse.emf.internal.cdo.protocol.LoadLibrariesRequest;
import org.eclipse.emf.internal.cdo.protocol.OpenSessionRequest;
import org.eclipse.emf.internal.cdo.protocol.OpenSessionResult;
import org.eclipse.emf.internal.cdo.protocol.RepositoryTimeRequest;
import org.eclipse.emf.internal.cdo.protocol.RepositoryTimeResult;
import org.eclipse.emf.internal.cdo.protocol.SetPassiveUpdateRequest;
import org.eclipse.emf.internal.cdo.protocol.SyncRevisionRequest;
import org.eclipse.emf.internal.cdo.protocol.ViewsChangedRequest;
import org.eclipse.emf.internal.cdo.util.CDOPackageRegistryImpl;
import org.eclipse.emf.internal.cdo.util.ModelUtil;
import org.eclipse.net4j.channel.IChannel;
import org.eclipse.net4j.connector.IConnector;
import org.eclipse.net4j.signal.failover.IFailOverEvent;
import org.eclipse.net4j.signal.failover.IFailOverStrategy;
import org.eclipse.net4j.signal.failover.NOOPFailOverStrategy;
import org.eclipse.net4j.util.ImplementationError;
import org.eclipse.net4j.util.WrappedException;
import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump;
import org.eclipse.net4j.util.concurrent.QueueRunner;
import org.eclipse.net4j.util.container.Container;
import org.eclipse.net4j.util.event.Event;
import org.eclipse.net4j.util.event.EventUtil;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.io.ExtendedDataInput;
import org.eclipse.net4j.util.io.ExtendedDataOutput;
import org.eclipse.net4j.util.io.IOUtil;
import org.eclipse.net4j.util.io.StringCompressor;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.eclipse.net4j.util.om.trace.ContextTracer;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* @author Eike Stepper
*/
public class CDOSessionImpl extends Container<CDOView> implements CDOSession, CDOIDObjectFactory,
CDOPackageURICompressor
{
private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, CDOSessionImpl.class);
private int sessionID;
private boolean passiveUpdateEnabled = true;
private CDOCollectionLoadingPolicy collectionLoadingPolicy;
private IFailOverStrategy failOverStrategy;
@ExcludeFromDump
private IListener failOverStrategyListener = new IListener()
{
public void notifyEvent(IEvent event)
{
if (event instanceof IFailOverEvent)
{
IFailOverEvent e = (IFailOverEvent)event;
handleFailOver(e.getOldChannel(), e.getNewChannel(), e.getNewConnector());
}
}
};
private IConnector connector;
private CDOClientProtocol protocol;
@ExcludeFromDump
private IListener channelListener = new LifecycleEventAdapter()
{
@Override
protected void onDeactivated(ILifecycle lifecycle)
{
close();
}
};
private String repositoryName;
private String repositoryUUID;
private long repositoryCreationTime;
private RepositoryTimeResult repositoryTimeResult;
private CDOPackageRegistry packageRegistry;
private CDOSessionPackageManagerImpl packageManager;
private CDORevisionManagerImpl revisionManager;
private Set<CDOViewImpl> views = new HashSet<CDOViewImpl>();
private QueueRunner invalidationRunner;
private Object invalidationRunnerLock = new Object();
@ExcludeFromDump
private transient Map<CDOID, InternalEObject> idToMetaInstanceMap = new HashMap<CDOID, InternalEObject>();
@ExcludeFromDump
private transient Map<InternalEObject, CDOID> metaInstanceToIDMap = new HashMap<InternalEObject, CDOID>();
@ExcludeFromDump
private transient int lastViewID;
@ExcludeFromDump
private transient int lastTempMetaID;
@ExcludeFromDump
private transient StringCompressor packageURICompressor;
@ExcludeFromDump
private CDOIDObjectFactory cdoidObjectFactory;
public CDOSessionImpl()
{
protocol = new CDOClientProtocol();
protocol.setInfraStructure(this);
packageManager = createPackageManager();
revisionManager = createRevisionManager();
// TODO Remove preferences from core
collectionLoadingPolicy = CDOUtil.createCollectionLoadingPolicy(OM.PREF_COLLECTION_LOADING_CHUNK_SIZE.getValue(),
OM.PREF_COLLECTION_LOADING_CHUNK_SIZE.getValue());
}
public int getSessionID()
{
return sessionID;
}
/**
* @since 2.0
*/
public String getUserID()
{
IChannel channel = protocol.getChannel();
return channel == null ? null : channel.getUserID();
}
public CDOIDObject createCDOIDObject(ExtendedDataInput in)
{
return cdoidObjectFactory.createCDOIDObject(in);
}
/**
* @since 2.0
*/
public CDOIDObject createCDOIDObject(String in)
{
return cdoidObjectFactory.createCDOIDObject(in);
}
/**
* @since 2.0
*/
public CDOCollectionLoadingPolicy getCollectionLoadingPolicy()
{
return collectionLoadingPolicy;
}
/**
* @since 2.0
*/
public void setCollectionLoadingPolicy(CDOCollectionLoadingPolicy policy)
{
if (policy == null)
{
policy = CDOCollectionLoadingPolicy.DEFAULT;
}
collectionLoadingPolicy = policy;
}
public synchronized IFailOverStrategy getFailOverStrategy()
{
if (failOverStrategy == null)
{
failOverStrategy = new NOOPFailOverStrategy();
}
return failOverStrategy;
}
public synchronized void setFailOverStrategy(IFailOverStrategy strategy)
{
if (failOverStrategy != null)
{
failOverStrategy.removeListener(failOverStrategyListener);
}
failOverStrategy = strategy;
if (failOverStrategy != null)
{
failOverStrategy.addListener(failOverStrategyListener);
}
}
public IConnector getConnector()
{
return connector;
}
public void setConnector(IConnector connector)
{
this.connector = connector;
}
/**
* @noreference This method is not intended to be referenced by clients.
*/
public CDOClientProtocol getProtocol()
{
return protocol;
}
public String getRepositoryName()
{
return repositoryName;
}
public void setRepositoryName(String repositoryName)
{
this.repositoryName = repositoryName;
}
public String getRepositoryUUID()
{
return repositoryUUID;
}
/**
* @since 2.0
*/
public long getRepositoryCreationTime()
{
checkActive();
return repositoryCreationTime;
}
/**
* @since 2.0
*/
public long getRepositoryTime()
{
return getRepositoryTime(false);
}
/**
* @since 2.0
*/
public long getRepositoryTime(boolean forceRefresh)
{
checkActive();
if (repositoryTimeResult == null || forceRefresh)
{
repositoryTimeResult = sendRepositoryTimeRequest();
}
return repositoryTimeResult.getAproximateRepositoryTime();
}
private RepositoryTimeResult sendRepositoryTimeRequest()
{
try
{
RepositoryTimeRequest request = new RepositoryTimeRequest(protocol);
return getFailOverStrategy().send(request);
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
public boolean isOpen()
{
IChannel channel = protocol.getChannel();
return channel != null;
}
public void close()
{
deactivate();
}
/**
* @since 2.0
*/
public boolean isClosed()
{
return !isActive();
}
/**
* @since 2.0
*/
public void setPackageRegistry(CDOPackageRegistry packageRegistry)
{
this.packageRegistry = packageRegistry;
}
public CDOPackageRegistry getPackageRegistry()
{
return packageRegistry;
}
public CDOSessionPackageManagerImpl getPackageManager()
{
return packageManager;
}
public CDORevisionManagerImpl getRevisionManager()
{
return revisionManager;
}
public CDOTransactionImpl openTransaction(ResourceSet resourceSet)
{
checkActive();
CDOTransactionImpl transaction = createTransaction(++lastViewID);
attach(resourceSet, transaction);
return transaction;
}
public CDOTransactionImpl openTransaction()
{
return openTransaction(createResourceSet());
}
protected CDOTransactionImpl createTransaction(int id)
{
return new CDOTransactionImpl(id, this);
}
public CDOViewImpl openView(ResourceSet resourceSet)
{
checkActive();
CDOViewImpl view = createView(++lastViewID);
attach(resourceSet, view);
return view;
}
public CDOViewImpl openView()
{
return openView(createResourceSet());
}
protected CDOViewImpl createView(int id)
{
return new CDOViewImpl(this, id);
}
public CDOAuditImpl openAudit(ResourceSet resourceSet, long timeStamp)
{
checkActive();
CDOAuditImpl audit = createAudit(++lastViewID, timeStamp);
attach(resourceSet, audit);
return audit;
}
public CDOAuditImpl openAudit(long timeStamp)
{
return openAudit(createResourceSet(), timeStamp);
}
protected CDOAuditImpl createAudit(int id, long timeStamp)
{
return new CDOAuditImpl(id, this, timeStamp);
}
public void viewDetached(CDOViewImpl view)
{
// Detach viewset from the view
((CDOViewSetImpl)view.getViewSet()).remove(view);
synchronized (views)
{
if (!views.remove(view))
{
return;
}
}
if (isActive())
{
try
{
ViewsChangedRequest request = new ViewsChangedRequest(protocol, view.getViewID(),
CDOProtocolConstants.VIEW_CLOSED, CDOProtocolView.UNSPECIFIED_DATE);
getFailOverStrategy().send(request);
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
fireElementRemovedEvent(view);
}
private void sendViewsChangedRequest(CDOViewImpl view)
{
try
{
int id = view.getViewID();
byte kind = getKind(view);
long timeStamp = CDOProtocolView.UNSPECIFIED_DATE;
if (view instanceof CDOAudit)
{
timeStamp = ((CDOAudit)view).getTimeStamp();
}
ViewsChangedRequest request = new ViewsChangedRequest(protocol, id, kind, timeStamp);
getFailOverStrategy().send(request);
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
private byte getKind(CDOViewImpl view)
{
CDOView.Type type = view.getViewType();
switch (type)
{
case TRANSACTION:
return CDOProtocolConstants.VIEW_TRANSACTION;
case READONLY:
return CDOProtocolConstants.VIEW_READONLY;
case AUDIT:
return CDOProtocolConstants.VIEW_AUDIT;
default:
throw new ImplementationError("Invalid view type: " + type);
}
}
public CDOView getView(int viewID)
{
checkActive();
for (CDOViewImpl view : getViews())
{
if (view.getViewID() == viewID)
{
return view;
}
}
return null;
}
public CDOViewImpl[] getViews()
{
checkActive();
synchronized (views)
{
return views.toArray(new CDOViewImpl[views.size()]);
}
}
public CDOView[] getElements()
{
return getViews();
}
@Override
public boolean isEmpty()
{
checkActive();
return views.isEmpty();
}
public synchronized CDOIDMetaRange getTempMetaIDRange(int count)
{
CDOIDTemp lowerBound = CDOIDUtil.createTempMeta(lastTempMetaID + 1);
lastTempMetaID += count;
return CDOIDUtil.createMetaRange(lowerBound, count);
}
public InternalEObject lookupMetaInstance(CDOID id)
{
InternalEObject metaInstance = idToMetaInstanceMap.get(id);
if (metaInstance == null)
{
CDOPackage[] cdoPackages = packageManager.getPackages();
for (CDOPackage cdoPackage : cdoPackages)
{
CDOIDMetaRange metaIDRange = cdoPackage.getMetaIDRange();
if (metaIDRange != null && metaIDRange.contains(id))
{
EPackage ePackage = ModelUtil.getEPackage(cdoPackage, packageRegistry);
registerEPackage(ePackage);
metaInstance = idToMetaInstanceMap.get(id);
break;
}
}
}
return metaInstance;
}
public CDOID lookupMetaInstanceID(InternalEObject metaInstance)
{
return metaInstanceToIDMap.get(metaInstance);
}
public void registerEPackage(EPackage ePackage, CDOIDMetaRange metaIDRange)
{
if (metaIDRange.isTemporary())
{
throw new IllegalArgumentException("metaIDRange.isTemporary()");
}
CDOIDMetaRange range = CDOIDUtil.createMetaRange(metaIDRange.getLowerBound(), 0);
range = registerMetaInstance((InternalEObject)ePackage, range, idToMetaInstanceMap, metaInstanceToIDMap);
if (range.size() != metaIDRange.size())
{
throw new IllegalStateException("range.size() != metaIDRange.size()");
}
}
public CDOIDMetaRange registerEPackage(EPackage ePackage)
{
CDOIDMetaRange range = registerEPackage(ePackage, lastTempMetaID + 1, idToMetaInstanceMap, metaInstanceToIDMap);
lastTempMetaID = ((CDOIDTempMeta)range.getUpperBound()).getIntValue();
return range;
}
public static CDOIDMetaRange registerEPackage(EPackage ePackage, int firstMetaID,
Map<CDOID, InternalEObject> idToMetaInstances, Map<InternalEObject, CDOID> metaInstanceToIDs)
{
CDOIDTemp lowerBound = CDOIDUtil.createTempMeta(firstMetaID);
CDOIDMetaRange range = CDOIDUtil.createMetaRange(lowerBound, 0);
range = registerMetaInstance((InternalEObject)ePackage, range, idToMetaInstances, metaInstanceToIDs);
return range;
}
public static CDOIDMetaRange registerMetaInstance(InternalEObject metaInstance, CDOIDMetaRange range,
Map<CDOID, InternalEObject> idToMetaInstances, Map<InternalEObject, CDOID> metaInstanceToIDs)
{
range = range.increase();
CDOID id = range.getUpperBound();
if (TRACER.isEnabled())
{
TRACER.format("Registering meta instance: {0} <-> {1}", id, metaInstance);
}
if (idToMetaInstances != null)
{
if (idToMetaInstances.put(id, metaInstance) != null)
{
throw new IllegalStateException("Duplicate meta ID: " + id + " --> " + metaInstance);
}
}
if (metaInstanceToIDs != null)
{
if (metaInstanceToIDs.put(metaInstance, id) != null)
{
throw new IllegalStateException("Duplicate metaInstance: " + metaInstance + " --> " + id);
}
}
for (EObject content : metaInstance.eContents())
{
range = registerMetaInstance((InternalEObject)content, range, idToMetaInstances, metaInstanceToIDs);
}
return range;
}
public void remapMetaInstance(CDOID oldID, CDOID newID)
{
InternalEObject metaInstance = idToMetaInstanceMap.remove(oldID);
if (metaInstance == null)
{
throw new IllegalArgumentException("Unknown meta instance id: " + oldID);
}
if (TRACER.isEnabled())
{
TRACER.format("Remapping meta instance: {0} --> {1} <-> {2}", oldID, newID, metaInstance);
}
idToMetaInstanceMap.put(newID, metaInstance);
metaInstanceToIDMap.put(metaInstance, newID);
}
/**
* @since 2.0
*/
public void handleCommitNotification(long timeStamp, Set<CDOIDAndVersion> dirtyOIDs,
Collection<CDOID> detachedObjects, Collection<CDORevisionDelta> deltas, CDOViewImpl excludedView)
{
if (isPassiveUpdateEnabled())
{
notifyInvalidation(timeStamp, dirtyOIDs, detachedObjects, excludedView);
}
handleChangeSubcription(deltas, detachedObjects, excludedView);
}
/**
* @since 2.0
*/
public void handleSyncResponse(long timestamp, Set<CDOIDAndVersion> dirtyOIDs, Collection<CDOID> detachedObjects)
{
notifyInvalidation(timestamp, dirtyOIDs, detachedObjects, null);
}
private void notifyInvalidation(final long timeStamp, Set<CDOIDAndVersion> dirtyOIDs,
Collection<CDOID> detachedObjects, CDOViewImpl excludedView)
{
for (CDOIDAndVersion dirtyOID : dirtyOIDs)
{
CDOID id = dirtyOID.getID();
int version = dirtyOID.getVersion();
InternalCDORevision revision = revisionManager.getRevisionByVersion(id, 0, version, false);
if (timeStamp == CDORevision.UNSPECIFIED_DATE)
{
revisionManager.removeCachedRevision(revision.getID(), revision.getVersion());
}
else if (revision != null)
{
revision.setRevised(timeStamp - 1);
}
}
for (CDOID id : detachedObjects)
{
InternalCDORevision revision = revisionManager.getRevision(id, 0, false);
if (timeStamp == CDORevision.UNSPECIFIED_DATE)
{
revisionManager.removeCachedRevision(revision.getID(), revision.getVersion());
}
else if (revision != null)
{
revision.setRevised(timeStamp - 1);
}
}
final Set<CDOIDAndVersion> finalDirtyOIDs = Collections.unmodifiableSet(dirtyOIDs);
final Collection<CDOID> finalDetachedObjects = Collections.unmodifiableCollection(detachedObjects);
for (final CDOViewImpl view : getViews())
{
if (view != excludedView)
{
QueueRunner runner = getInvalidationRunner();
runner.addWork(new Runnable()
{
public void run()
{
try
{
view.handleInvalidation(timeStamp, finalDirtyOIDs, finalDetachedObjects);
}
catch (RuntimeException ex)
{
OM.LOG.error(ex);
}
}
});
}
}
fireInvalidationEvent(timeStamp, dirtyOIDs, detachedObjects, excludedView);
}
private QueueRunner getInvalidationRunner()
{
synchronized (invalidationRunnerLock)
{
if (invalidationRunner == null)
{
invalidationRunner = new QueueRunner();
invalidationRunner.activate();
}
}
return invalidationRunner;
}
private void handleChangeSubcription(Collection<CDORevisionDelta> deltas, Collection<CDOID> detachedObjects,
CDOViewImpl excludedView)
{
if ((deltas == null || deltas.size() <= 0) && (detachedObjects == null || detachedObjects.size() <= 0))
{
return;
}
for (CDOViewImpl view : getViews())
{
if (view != excludedView)
{
try
{
view.handleChangeSubscription(deltas, detachedObjects);
}
catch (RuntimeException ex)
{
OM.LOG.error(ex);
}
}
}
}
/**
* @since 2.0
*/
public void fireInvalidationEvent(long timeStamp, Set<CDOIDAndVersion> dirtyOIDs, Collection<CDOID> detachedObjects,
CDOViewImpl excludedView)
{
fireEvent(new InvalidationEvent(excludedView, timeStamp, dirtyOIDs, detachedObjects));
}
/**
* @since 2.0
*/
public void writePackageURI(ExtendedDataOutput out, String uri) throws IOException
{
packageURICompressor.write(out, uri);
}
/**
* @since 2.0
*/
public String readPackageURI(ExtendedDataInput in) throws IOException
{
return packageURICompressor.read(in);
}
@Override
public String toString()
{
IChannel channel = protocol.getChannel();
return MessageFormat.format("CDOSession[{0}/{1}]", channel, repositoryName);
}
/**
* @since 2.0
*/
protected CDOPackageRegistry createPackageRegistry()
{
return new CDOPackageRegistryImpl();
}
protected CDOSessionPackageManagerImpl createPackageManager()
{
return new CDOSessionPackageManagerImpl(this);
}
protected CDORevisionManagerImpl createRevisionManager()
{
return new CDORevisionManagerImpl(this);
}
protected ResourceSet createResourceSet()
{
return new ResourceSetImpl();
}
protected void attach(ResourceSet resourceSet, CDOViewImpl view)
{
CDOViewSet viewSet = CDOSessionImpl.prepareResourceSet(resourceSet);
synchronized (views)
{
views.add(view);
}
// Link ViewSet with View
view.setViewSet(viewSet);
((CDOViewSetImpl)viewSet).add(view);
sendViewsChangedRequest(view);
fireElementAddedEvent(view);
}
protected void handleFailOver(IChannel oldChannel, IChannel newChannel, IConnector newConnector)
{
// TODO: implement CDOSessionImpl.handleFailOver(oldChannel, newChannel, newConnector)
throw new UnsupportedOperationException();
// EventUtil.removeListener(oldChannel, channelListener);
// EventUtil.addListener(newChannel, channelListener);
// channel = newChannel;
// connector = newConnector;
}
@Override
protected void doBeforeActivate() throws Exception
{
super.doBeforeActivate();
checkState(connector, "connector == null");
checkState(repositoryName, "repositoryName == null");
}
@Override
protected void doActivate() throws Exception
{
super.doActivate();
if (packageRegistry == null)
{
packageRegistry = createPackageRegistry();
}
packageRegistry.setSession(this);
IChannel channel = protocol.open(connector);
OpenSessionRequest request = new OpenSessionRequest(protocol, repositoryName, passiveUpdateEnabled);
OpenSessionResult result = getFailOverStrategy().send(request);
sessionID = result.getSessionID();
repositoryUUID = result.getRepositoryUUID();
repositoryCreationTime = result.getRepositoryCreationTime();
repositoryTimeResult = result.getRepositoryTimeResult();
handleLibraryDescriptor(result.getLibraryDescriptor());
packageURICompressor = result.getCompressor();
packageManager.addPackageProxies(result.getPackageInfos());
packageManager.activate();
revisionManager.activate();
EventUtil.addListener(channel, channelListener);
}
@Override
protected void doDeactivate() throws Exception
{
IChannel channel = protocol.getChannel();
EventUtil.removeListener(channel, channelListener);
if (invalidationRunner != null)
{
invalidationRunner.deactivate();
invalidationRunner = null;
}
revisionManager.deactivate();
revisionManager = null;
packageManager.deactivate();
packageManager = null;
for (CDOViewImpl view : views.toArray(new CDOViewImpl[views.size()]))
{
try
{
view.close();
}
catch (RuntimeException ignore)
{
}
}
views.clear();
views = null;
channel.close();
channel = null;
super.doDeactivate();
}
private void handleLibraryDescriptor(CDOIDLibraryDescriptor libraryDescriptor) throws Exception
{
String factoryName = libraryDescriptor.getFactoryName();
if (TRACER.isEnabled())
{
TRACER.format("Using CDOID factory: {0}", factoryName);
}
File cacheFolder = getCacheFolder();
ClassLoader classLoader = OM.class.getClassLoader();
Set<String> neededLibraries = createSet(libraryDescriptor.getLibraryNames());
if (!neededLibraries.isEmpty())
{
IOUtil.mkdirs(cacheFolder);
Set<String> existingLibraries = createSet(cacheFolder.list());
Set<String> missingLibraries = new HashSet<String>(neededLibraries);
missingLibraries.removeAll(existingLibraries);
if (!missingLibraries.isEmpty())
{
LoadLibrariesRequest request = new LoadLibrariesRequest(protocol, missingLibraries, cacheFolder);
getFailOverStrategy().send(request);
}
}
int i = 0;
URL[] urls = new URL[neededLibraries.size()];
for (String neededLibrary : neededLibraries)
{
File lib = new File(cacheFolder, neededLibrary);
if (TRACER.isEnabled())
{
TRACER.format("Using CDOID library: {0}", lib.getAbsolutePath());
}
urls[i++] = new URL("file:///" + lib.getAbsolutePath());
}
classLoader = new URLClassLoader(urls, classLoader);
Class<?> factoryClass = classLoader.loadClass(factoryName);
cdoidObjectFactory = (CDOIDObjectFactory)factoryClass.newInstance();
}
private File getCacheFolder()
{
String stateLocation = OM.BUNDLE.getStateLocation();
File repos = new File(stateLocation, "repos");
return new File(repos, repositoryUUID);
}
private Set<String> createSet(String[] fileNames)
{
Set<String> set = new HashSet<String>();
for (String fileName : fileNames)
{
if (fileName.endsWith(".jar"))
{
set.add(fileName);
}
}
return set;
}
/**
* @since 2.0
*/
public boolean isPassiveUpdateEnabled()
{
return passiveUpdateEnabled;
}
private Map<CDOID, CDORevision> getAllRevisions()
{
Map<CDOID, CDORevision> uniqueObjects = new HashMap<CDOID, CDORevision>();
for (CDOViewImpl view : getViews())
{
for (InternalCDOObject internalCDOObject : view.getObjectsArray())
{
if (internalCDOObject.cdoRevision() != null && !internalCDOObject.cdoID().isTemporary()
&& !uniqueObjects.containsKey(internalCDOObject.cdoID()))
{
uniqueObjects.put(internalCDOObject.cdoID(), internalCDOObject.cdoRevision());
}
}
}
// Need to add Revision from revisionManager since we do not have all objects in view.
for (CDORevision revision : getRevisionManager().getCachedRevisions())
{
if (!uniqueObjects.containsKey(revision.getID()))
{
uniqueObjects.put(revision.getID(), revision);
}
}
return uniqueObjects;
}
/**
* @since 2.0
*/
public void setPassiveUpdateEnabled(boolean passiveUpdateEnabled)
{
if (this.passiveUpdateEnabled != passiveUpdateEnabled)
{
this.passiveUpdateEnabled = passiveUpdateEnabled;
// Need to refresh if we change state
Map<CDOID, CDORevision> allRevisions = getAllRevisions();
try
{
if (!allRevisions.isEmpty())
{
SetPassiveUpdateRequest request = new SetPassiveUpdateRequest(protocol, this, allRevisions,
collectionLoadingPolicy.getInitialChunkSize(), passiveUpdateEnabled);
getFailOverStrategy().send(request);
}
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
}
/**
* @since 2.0
*/
public Collection<CDOTimestampContext> refresh()
{
// If passive update is turned on we don`t need to refresh.
// We do not throw an exception since the client could turn that feature on or off without affecting their code.
checkActive();
if (!isPassiveUpdateEnabled())
{
Map<CDOID, CDORevision> allRevisions = getAllRevisions();
try
{
if (!allRevisions.isEmpty())
{
SyncRevisionRequest request = new SyncRevisionRequest(protocol, this, allRevisions, collectionLoadingPolicy
.getInitialChunkSize());
return getFailOverStrategy().send(request);
}
}
catch (Exception ex)
{
throw WrappedException.wrap(ex);
}
}
return Collections.emptyList();
}
/**
* @since 2.0
*/
public static CDOViewSet prepareResourceSet(ResourceSet resourceSet)
{
CDOViewSetImpl viewSet = null;
synchronized (resourceSet)
{
viewSet = (CDOViewSetImpl)CDOUtil.getViewSet(resourceSet);
if (viewSet == null)
{
viewSet = new CDOViewSetImpl();
resourceSet.eAdapters().add(viewSet);
}
}
return viewSet;
}
/**
* @author Eike Stepper
*/
private final class InvalidationEvent extends Event implements CDOSessionInvalidationEvent
{
private static final long serialVersionUID = 1L;
private CDOViewImpl view;
private long timeStamp;
private Set<CDOIDAndVersion> dirtyOIDs;
private Collection<CDOID> detachedObjects;
public InvalidationEvent(CDOViewImpl view, long timeStamp, Set<CDOIDAndVersion> dirtyOIDs,
Collection<CDOID> detachedObjects)
{
super(CDOSessionImpl.this);
this.view = view;
this.timeStamp = timeStamp;
this.dirtyOIDs = dirtyOIDs;
this.detachedObjects = detachedObjects;
}
public CDOSession getSession()
{
return CDOSessionImpl.this;
}
public CDOViewImpl getView()
{
return view;
}
public long getTimeStamp()
{
return timeStamp;
}
public Set<CDOIDAndVersion> getDirtyOIDs()
{
return dirtyOIDs;
}
public Collection<CDOID> getDetachedObjects()
{
return detachedObjects;
}
@Override
public String toString()
{
return "CDOSessionInvalidationEvent: " + dirtyOIDs;
}
}
}