diff options
Diffstat (limited to 'plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java')
-rw-r--r-- | plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java | 1169 |
1 files changed, 1169 insertions, 0 deletions
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java new file mode 100644 index 0000000000..3fb781b7de --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/session/CDOSessionImpl.java @@ -0,0 +1,1169 @@ +/*************************************************************************** + * 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 + * Victor Roldan Betancort - maintenance + **************************************************************************/ +package org.eclipse.emf.internal.cdo.session; + +import org.eclipse.emf.cdo.CDOObject; +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.io.CDODataInput; +import org.eclipse.emf.cdo.common.model.CDOClass; +import org.eclipse.emf.cdo.common.model.CDOPackage; +import org.eclipse.emf.cdo.common.revision.CDORevision; +import org.eclipse.emf.cdo.common.revision.CDORevisionFactory; +import org.eclipse.emf.cdo.common.revision.CDORevisionUtil; +import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; +import org.eclipse.emf.cdo.session.CDOCollectionLoadingPolicy; +import org.eclipse.emf.cdo.session.CDOPackageRegistry; +import org.eclipse.emf.cdo.session.CDOSession; +import org.eclipse.emf.cdo.session.CDOSessionInvalidationEvent; +import org.eclipse.emf.cdo.session.CDOSession.Repository; +import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; +import org.eclipse.emf.cdo.transaction.CDOTimeStampContext; +import org.eclipse.emf.cdo.util.CDOUtil; +import org.eclipse.emf.cdo.view.CDOView; + +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.transaction.CDOTransactionImpl; +import org.eclipse.emf.internal.cdo.util.ModelUtil; +import org.eclipse.emf.internal.cdo.view.CDOAuditImpl; +import org.eclipse.emf.internal.cdo.view.CDOViewImpl; + +import org.eclipse.net4j.channel.IChannel; +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.IListener; +import org.eclipse.net4j.util.event.Notifier; +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.lifecycle.LifecycleUtil; +import org.eclipse.net4j.util.om.trace.ContextTracer; +import org.eclipse.net4j.util.options.IOptions; +import org.eclipse.net4j.util.options.IOptionsContainer; +import org.eclipse.net4j.util.options.OptionsEvent; + +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 org.eclipse.emf.spi.cdo.InternalCDOObject; +import org.eclipse.emf.spi.cdo.InternalCDOSession; +import org.eclipse.emf.spi.cdo.InternalCDOTransaction; +import org.eclipse.emf.spi.cdo.InternalCDOView; +import org.eclipse.emf.spi.cdo.InternalCDOViewSet; + +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 InternalCDOSession, Repository +{ + private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_SESSION, CDOSessionImpl.class); + + private int sessionID; + + private CDOClientProtocol protocol; + + @ExcludeFromDump + private IListener protocolListener = new LifecycleEventAdapter() + { + @Override + protected void onDeactivated(ILifecycle lifecycle) + { + close(); + } + }; + + private String repositoryName; + + private String repositoryUUID; + + private long repositoryCreationTime; + + private RepositoryTimeResult repositoryTimeResult; + + private boolean repositorySupportingAudits; + + private CDOPackageRegistry packageRegistry; + + private CDOSessionPackageManagerImpl packageManager; + + private CDORevisionManagerImpl revisionManager; + + private Set<InternalCDOView> views = new HashSet<InternalCDOView>(); + + 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; + + /** + * @since 2.0 + */ + protected IOptions options = new OptionsImpl(); + + public CDOSessionImpl() + { + protocol = new CDOClientProtocol(); + protocol.setInfraStructure(this); + + packageManager = createPackageManager(); + revisionManager = createRevisionManager(); + } + + public int getSessionID() + { + return sessionID; + } + + /** + * @since 2.0 + */ + public Options options() + { + return (Options)options; + } + + /** + * @since 2.0 + */ + public Repository repository() + { + return this; + } + + /** + * @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); + } + + public CDOClientProtocol getProtocol() + { + return protocol; + } + + /** + * @since 2.0 + */ + public String getName() + { + return repositoryName; + } + + public void setRepositoryName(String repositoryName) + { + this.repositoryName = repositoryName; + } + + /** + * @since 2.0 + */ + public String getUUID() + { + return repositoryUUID; + } + + /** + * @since 2.0 + */ + public long getCreationTime() + { + checkActive(); + return repositoryCreationTime; + } + + /** + * @since 2.0 + */ + public long getCurrentTime() + { + return getCurrentTime(false); + } + + /** + * @since 2.0 + */ + public long getCurrentTime(boolean forceRefresh) + { + checkActive(); + if (repositoryTimeResult == null || forceRefresh) + { + repositoryTimeResult = sendRepositoryTimeRequest(); + } + + return repositoryTimeResult.getAproximateRepositoryTime(); + } + + private RepositoryTimeResult sendRepositoryTimeRequest() + { + try + { + return new RepositoryTimeRequest(protocol).send(); + } + catch (Exception ex) + { + throw WrappedException.wrap(ex); + } + } + + /** + * @since 2.0 + */ + public boolean isSupportingAudits() + { + return repositorySupportingAudits; + } + + 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; + } + + /** + * @since 2.0 + */ + public InternalCDOTransaction openTransaction(ResourceSet resourceSet) + { + checkActive(); + InternalCDOTransaction transaction = createTransaction(); + initView(transaction, resourceSet); + return transaction; + } + + /** + * @since 2.0 + */ + public InternalCDOTransaction openTransaction() + { + return openTransaction(createResourceSet()); + } + + /** + * @since 2.0 + */ + protected InternalCDOTransaction createTransaction() + { + return new CDOTransactionImpl(); + } + + /** + * @since 2.0 + */ + public InternalCDOView openView(ResourceSet resourceSet) + { + checkActive(); + InternalCDOView view = createView(); + initView(view, resourceSet); + return view; + } + + /** + * @since 2.0 + */ + public InternalCDOView openView() + { + return openView(createResourceSet()); + } + + /** + * @since 2.0 + */ + protected InternalCDOView createView() + { + return new CDOViewImpl(); + } + + public CDOAuditImpl openAudit(ResourceSet resourceSet, long timeStamp) + { + checkActive(); + CDOAuditImpl audit = createAudit(timeStamp); + initView(audit, resourceSet); + return audit; + } + + public CDOAuditImpl openAudit(long timeStamp) + { + return openAudit(createResourceSet(), timeStamp); + } + + /** + * @since 2.0 + */ + protected CDOAuditImpl createAudit(long timeStamp) + { + return new CDOAuditImpl(timeStamp); + } + + /** + * @since 2.0 + */ + public void viewDetached(InternalCDOView view) + { + // Detach viewset from the view + view.getViewSet().remove(view); + synchronized (views) + { + if (!views.remove(view)) + { + return; + } + } + + if (isActive()) + { + try + { + LifecycleUtil.deactivate(view); + // new ViewsChangedRequest(protocol, view.getViewID(), CDOProtocolConstants.VIEW_CLOSED, + // CDOCommonView.UNSPECIFIED_DATE).send(); + } + catch (Exception ex) + { + throw WrappedException.wrap(ex); + } + } + + fireElementRemovedEvent(view); + } + + public CDOView getView(int viewID) + { + checkActive(); + for (InternalCDOView view : getViews()) + { + if (view.getViewID() == viewID) + { + return view; + } + } + + return null; + } + + /** + * @since 2.0 + */ + public InternalCDOView[] getViews() + { + checkActive(); + synchronized (views) + { + return views.toArray(new InternalCDOView[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 = SessionUtil + .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 = SessionUtil.registerEPackage(ePackage, lastTempMetaID + 1, idToMetaInstanceMap, + metaInstanceToIDMap); + lastTempMetaID = ((CDOIDTempMeta)range.getUpperBound()).getIntValue(); + 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 handleSyncResponse(long timestamp, Set<CDOIDAndVersion> dirtyOIDs, Collection<CDOID> detachedObjects) + { + handleCommitNotification(timestamp, dirtyOIDs, detachedObjects, null, null, true, false); + } + + /** + * @since 2.0 + */ + public void handleCommitNotification(final long timeStamp, Set<CDOIDAndVersion> dirtyOIDs, + final Collection<CDOID> detachedObjects, final Collection<CDORevisionDelta> deltas, InternalCDOView excludedView) + { + handleCommitNotification(timeStamp, dirtyOIDs, detachedObjects, deltas, excludedView, options() + .isPassiveUpdateEnabled(), true); + } + + private void handleCommitNotification(final long timeStamp, Set<CDOIDAndVersion> dirtyOIDs, + final Collection<CDOID> detachedObjects, final Collection<CDORevisionDelta> deltas, InternalCDOView excludedView, + final boolean passiveUpdate, boolean async) + { + if (passiveUpdate) + { + updateRevisionForRemoteChanges(timeStamp, dirtyOIDs, detachedObjects, excludedView); + } + + final Set<CDOIDAndVersion> finalDirtyOIDs = Collections.unmodifiableSet(dirtyOIDs); + final Collection<CDOID> finalDetachedObjects = Collections.unmodifiableCollection(detachedObjects); + final boolean skipChangeSubscription = (deltas == null || deltas.size() <= 0) + && (detachedObjects == null || detachedObjects.size() <= 0); + + for (final InternalCDOView view : getViews()) + { + if (view != excludedView) + { + Runnable runnable = new Runnable() + { + public void run() + { + try + { + Set<CDOObject> conflicts = null; + if (passiveUpdate) + { + conflicts = view.handleInvalidation(timeStamp, finalDirtyOIDs, finalDetachedObjects); + } + + if (!skipChangeSubscription) + { + view.handleChangeSubscription(deltas, detachedObjects); + } + + if (conflicts != null) + { + ((InternalCDOTransaction)view).handleConflicts(conflicts); + } + } + catch (RuntimeException ex) + { + OM.LOG.error(ex); + } + } + }; + + if (async) + { + QueueRunner runner = getInvalidationRunner(); + runner.addWork(runnable); + } + else + { + runnable.run(); + } + } + } + + fireInvalidationEvent(timeStamp, dirtyOIDs, detachedObjects, excludedView); + } + + private void updateRevisionForRemoteChanges(final long timeStamp, Set<CDOIDAndVersion> dirtyOIDs, + Collection<CDOID> detachedObjects, InternalCDOView excludedView) + { + // revised is done automatically when postCommit is CDOTransaction.postCommit is happening + // Detached are not revised through postCommit + if (excludedView == null || timeStamp == CDORevision.UNSPECIFIED_DATE) + { + 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); + } + } + } + + private QueueRunner getInvalidationRunner() + { + synchronized (invalidationRunnerLock) + { + if (invalidationRunner == null) + { + invalidationRunner = new QueueRunner(); + invalidationRunner.activate(); + } + } + + return invalidationRunner; + } + + /** + * @since 2.0 + */ + public void fireInvalidationEvent(long timeStamp, Set<CDOIDAndVersion> dirtyOIDs, Collection<CDOID> detachedObjects, + InternalCDOView 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(); + } + + /** + * @since 2.0 + */ + protected void initView(InternalCDOView view, ResourceSet resourceSet) + { + InternalCDOViewSet viewSet = SessionUtil.prepareResourceSet(resourceSet); + synchronized (views) + { + view.setSession(this); + view.setViewID(++lastViewID); + views.add(view); + } + + // Link ViewSet with View + view.setViewSet(viewSet); + viewSet.add(view); + + try + { + view.activate(); + fireElementAddedEvent(view); + } + catch (RuntimeException ex) + { + synchronized (views) + { + views.remove(view); + } + + viewSet.remove(view); + throw ex; + } + } + + @Override + protected void doBeforeActivate() throws Exception + { + super.doBeforeActivate(); + checkState(repositoryName, "repositoryName == null"); + } + + @Override + protected void doActivate() throws Exception + { + super.doActivate(); + if (packageRegistry == null) + { + packageRegistry = createPackageRegistry(); + } + + packageRegistry.setSession(this); + protocol.open(); + + boolean passiveUpdateEnabled = options().isPassiveUpdateEnabled(); + OpenSessionResult result = new OpenSessionRequest(protocol, repositoryName, passiveUpdateEnabled).send(); + sessionID = result.getSessionID(); + repositoryUUID = result.getRepositoryUUID(); + repositoryCreationTime = result.getRepositoryCreationTime(); + repositoryTimeResult = result.getRepositoryTimeResult(); + repositorySupportingAudits = result.isRepositorySupportingAudits(); + handleLibraryDescriptor(result.getLibraryDescriptor()); + packageURICompressor = result.getCompressor(); + packageManager.addPackageProxies(result.getPackageInfos()); + packageManager.activate(); + revisionManager.activate(); + EventUtil.addListener(protocol, protocolListener); + } + + @Override + protected void doDeactivate() throws Exception + { + for (InternalCDOView view : views.toArray(new InternalCDOView[views.size()])) + { + try + { + view.close(); + } + catch (RuntimeException ignore) + { + } + } + + views.clear(); + views = null; + + if (invalidationRunner != null) + { + invalidationRunner.deactivate(); + invalidationRunner = null; + } + + revisionManager.deactivate(); + revisionManager = null; + + packageManager.deactivate(); + packageManager = null; + + EventUtil.removeListener(protocol, protocolListener); + protocol.close(); + protocol = 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()) + { + new LoadLibrariesRequest(protocol, missingLibraries, cacheFolder).send(); + } + } + + 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; + } + + private Map<CDOID, CDORevision> getAllRevisions() + { + Map<CDOID, CDORevision> uniqueObjects = new HashMap<CDOID, CDORevision>(); + for (InternalCDOView 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 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 (!options().isPassiveUpdateEnabled()) + { + Map<CDOID, CDORevision> allRevisions = getAllRevisions(); + + try + { + if (!allRevisions.isEmpty()) + { + int initialChunkSize = options().getCollectionLoadingPolicy().getInitialChunkSize(); + return new SyncRevisionRequest(protocol, this, allRevisions, initialChunkSize).send(); + } + } + catch (Exception ex) + { + throw WrappedException.wrap(ex); + } + } + + return Collections.emptyList(); + } + + /** + * @author Eike Stepper + */ + private final class InvalidationEvent extends Event implements CDOSessionInvalidationEvent + { + private static final long serialVersionUID = 1L; + + private InternalCDOView view; + + private long timeStamp; + + private Set<CDOIDAndVersion> dirtyOIDs; + + private Collection<CDOID> detachedObjects; + + public InvalidationEvent(InternalCDOView 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 (CDOSession)getSource(); + } + + public InternalCDOView 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; + } + } + + /** + * @author Eike Stepper + * @since 2.0 + */ + protected class OptionsImpl extends Notifier implements Options + { + private boolean passiveUpdateEnabled = true; + + private CDOCollectionLoadingPolicy collectionLoadingPolicy; + + private CDORevisionFactory revisionFactory; + + public OptionsImpl() + { + // TODO Remove preferences from core + int value = OM.PREF_COLLECTION_LOADING_CHUNK_SIZE.getValue(); + collectionLoadingPolicy = CDOUtil.createCollectionLoadingPolicy(value, value); + } + + public IOptionsContainer getContainer() + { + return CDOSessionImpl.this; + } + + 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()) + { + new SetPassiveUpdateRequest(protocol, CDOSessionImpl.this, allRevisions, collectionLoadingPolicy + .getInitialChunkSize(), passiveUpdateEnabled).send(); + } + } + catch (Exception ex) + { + throw WrappedException.wrap(ex); + } + + fireEvent(new PassiveUpdateEventImpl()); + } + } + + public boolean isPassiveUpdateEnabled() + { + return passiveUpdateEnabled; + } + + public CDOCollectionLoadingPolicy getCollectionLoadingPolicy() + { + return collectionLoadingPolicy; + } + + public void setCollectionLoadingPolicy(CDOCollectionLoadingPolicy policy) + { + if (policy == null) + { + policy = CDOCollectionLoadingPolicy.DEFAULT; + } + + if (collectionLoadingPolicy != policy) + { + collectionLoadingPolicy = policy; + fireEvent(new CollectionLoadingPolicyEventImpl()); + } + } + + public synchronized CDORevisionFactory getRevisionFactory() + { + if (revisionFactory == null) + { + revisionFactory = new CDORevisionFactory() + { + public CDORevision createRevision(CDOClass cdoClass, CDOID id) + { + return CDORevisionUtil.create(cdoClass, id); + } + + public CDORevision createRevision(CDODataInput in) throws IOException + { + return CDORevisionUtil.read(in); + } + + @Override + public String toString() + { + return "DefaultRevisionFactory"; + } + }; + } + + return revisionFactory; + } + + public synchronized void setRevisionFactory(CDORevisionFactory revisionFactory) + { + if (this.revisionFactory != revisionFactory) + { + this.revisionFactory = revisionFactory; + fireEvent(new RevisionFactoryEventImpl()); + } + } + + /** + * @author Eike Stepper + */ + private final class PassiveUpdateEventImpl extends OptionsEvent implements PassiveUpdateEvent + { + private static final long serialVersionUID = 1L; + + public PassiveUpdateEventImpl() + { + super(OptionsImpl.this); + } + } + + /** + * @author Eike Stepper + */ + private final class CollectionLoadingPolicyEventImpl extends OptionsEvent implements CollectionLoadingPolicyEvent + { + private static final long serialVersionUID = 1L; + + public CollectionLoadingPolicyEventImpl() + { + super(OptionsImpl.this); + } + } + + /** + * @author Eike Stepper + */ + private final class RevisionFactoryEventImpl extends OptionsEvent implements RevisionFactoryEvent + { + private static final long serialVersionUID = 1L; + + public RevisionFactoryEventImpl() + { + super(OptionsImpl.this); + } + } + } +} |