| /* |
| * Copyright (c) 2010-2014 Eike Stepper (Berlin, Germany) 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: |
| * Eike Stepper - initial API and implementation |
| * Simon McDuff - maintenance |
| * Victor Roldan Betancort - maintenance |
| */ |
| package org.eclipse.emf.internal.cdo.view; |
| |
| import org.eclipse.emf.cdo.CDOObject; |
| import org.eclipse.emf.cdo.CDOObjectHistory; |
| import org.eclipse.emf.cdo.CDOObjectReference; |
| import org.eclipse.emf.cdo.CDOState; |
| import org.eclipse.emf.cdo.common.branch.CDOBranch; |
| import org.eclipse.emf.cdo.common.branch.CDOBranchManager; |
| import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; |
| import org.eclipse.emf.cdo.common.commit.CDOChangeSetData; |
| import org.eclipse.emf.cdo.common.commit.CDOCommitHistory; |
| import org.eclipse.emf.cdo.common.commit.CDOCommitInfoManager; |
| import org.eclipse.emf.cdo.common.id.CDOID; |
| import org.eclipse.emf.cdo.common.id.CDOIDExternal; |
| import org.eclipse.emf.cdo.common.id.CDOIDUtil; |
| import org.eclipse.emf.cdo.common.id.CDOWithID; |
| import org.eclipse.emf.cdo.common.model.CDOClassifierRef; |
| import org.eclipse.emf.cdo.common.model.CDOModelUtil; |
| import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants; |
| import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; |
| import org.eclipse.emf.cdo.common.revision.CDOList; |
| import org.eclipse.emf.cdo.common.revision.CDORevision; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionData; |
| import org.eclipse.emf.cdo.common.revision.CDORevisionKey; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDOListFeatureDelta; |
| import org.eclipse.emf.cdo.common.revision.delta.CDORevisionDelta; |
| import org.eclipse.emf.cdo.common.security.CDOPermission; |
| import org.eclipse.emf.cdo.common.util.CDOCommonUtil; |
| import org.eclipse.emf.cdo.common.util.CDOException; |
| import org.eclipse.emf.cdo.eresource.CDOBinaryResource; |
| import org.eclipse.emf.cdo.eresource.CDOResource; |
| import org.eclipse.emf.cdo.eresource.CDOResourceFolder; |
| import org.eclipse.emf.cdo.eresource.CDOResourceNode; |
| import org.eclipse.emf.cdo.eresource.CDOTextResource; |
| import org.eclipse.emf.cdo.eresource.EresourcePackage; |
| import org.eclipse.emf.cdo.eresource.impl.CDOResourceImpl; |
| import org.eclipse.emf.cdo.internal.common.commit.CDOCommitHistoryProviderImpl; |
| import org.eclipse.emf.cdo.internal.common.revision.delta.CDORevisionDeltaImpl; |
| import org.eclipse.emf.cdo.session.CDOSession; |
| import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil; |
| import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevision; |
| import org.eclipse.emf.cdo.transaction.CDOTransaction; |
| import org.eclipse.emf.cdo.util.CDOURIUtil; |
| import org.eclipse.emf.cdo.util.CDOUtil; |
| import org.eclipse.emf.cdo.util.DanglingReferenceException; |
| import org.eclipse.emf.cdo.util.InvalidURIException; |
| import org.eclipse.emf.cdo.util.ObjectNotFoundException; |
| import org.eclipse.emf.cdo.util.ReadOnlyException; |
| import org.eclipse.emf.cdo.view.CDOAdapterPolicy; |
| import org.eclipse.emf.cdo.view.CDOObjectHandler; |
| import org.eclipse.emf.cdo.view.CDOQuery; |
| import org.eclipse.emf.cdo.view.CDOView; |
| import org.eclipse.emf.cdo.view.CDOViewAdaptersNotifiedEvent; |
| import org.eclipse.emf.cdo.view.CDOViewEvent; |
| import org.eclipse.emf.cdo.view.CDOViewProvider; |
| import org.eclipse.emf.cdo.view.CDOViewTargetChangedEvent; |
| |
| import org.eclipse.emf.internal.cdo.bundle.OM; |
| import org.eclipse.emf.internal.cdo.messages.Messages; |
| import org.eclipse.emf.internal.cdo.object.CDOLegacyAdapter; |
| import org.eclipse.emf.internal.cdo.query.CDOQueryImpl; |
| import org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl; |
| |
| import org.eclipse.net4j.util.AdapterUtil; |
| import org.eclipse.net4j.util.CheckUtil; |
| import org.eclipse.net4j.util.ImplementationError; |
| import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; |
| import org.eclipse.net4j.util.StringUtil; |
| import org.eclipse.net4j.util.WrappedException; |
| import org.eclipse.net4j.util.collection.CloseableIterator; |
| import org.eclipse.net4j.util.collection.ConcurrentArray; |
| import org.eclipse.net4j.util.collection.Pair; |
| import org.eclipse.net4j.util.container.IContainerDelta; |
| import org.eclipse.net4j.util.container.IContainerEvent; |
| import org.eclipse.net4j.util.container.SingleDeltaContainerEvent; |
| import org.eclipse.net4j.util.event.IListener; |
| import org.eclipse.net4j.util.lifecycle.LifecycleException; |
| import org.eclipse.net4j.util.lifecycle.LifecycleUtil; |
| import org.eclipse.net4j.util.om.log.OMLogger; |
| import org.eclipse.net4j.util.om.trace.ContextTracer; |
| import org.eclipse.net4j.util.ref.KeyedReference; |
| import org.eclipse.net4j.util.ref.ReferenceType; |
| import org.eclipse.net4j.util.ref.ReferenceValueMap2; |
| import org.eclipse.net4j.util.registry.HashMapRegistry; |
| import org.eclipse.net4j.util.registry.IRegistry; |
| |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notification; |
| import org.eclipse.emf.common.notify.impl.AdapterImpl; |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.InternalEObject; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.spi.cdo.CDOStore; |
| import org.eclipse.emf.spi.cdo.FSMUtil; |
| import org.eclipse.emf.spi.cdo.InternalCDOObject; |
| import org.eclipse.emf.spi.cdo.InternalCDOSession; |
| import org.eclipse.emf.spi.cdo.InternalCDOView; |
| import org.eclipse.emf.spi.cdo.InternalCDOViewSet; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| |
| import java.io.IOException; |
| import java.text.MessageFormat; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Set; |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOObject, CDOObjectHistory> |
| implements InternalCDOView |
| { |
| private static final ContextTracer TRACER = new ContextTracer(OM.DEBUG_VIEW, AbstractCDOView.class); |
| |
| private static final String REPOSITORY_NAME_KEY = "cdo.repository.name"; |
| |
| private final ViewAndState[] viewAndStates = ViewAndState.create(this); |
| |
| private final CDOURIHandler uriHandler = new CDOURIHandler(this); |
| |
| private CDOBranchPoint branchPoint; |
| |
| private CDOBranchPoint normalizedBranchPoint; |
| |
| private CDOViewProvider provider; |
| |
| private InternalCDOViewSet viewSet; |
| |
| private Map<CDOID, InternalCDOObject> objects; |
| |
| private CDOStore store = new CDOStoreImpl(this); |
| |
| private CDOResourceImpl rootResource; |
| |
| private final ConcurrentArray<CDOObjectHandler> objectHandlers = new ConcurrentArray<CDOObjectHandler>() |
| { |
| @Override |
| protected CDOObjectHandler[] newArray(int length) |
| { |
| return new CDOObjectHandler[length]; |
| } |
| }; |
| |
| private final IRegistry<String, Object> properties = new HashMapRegistry<String, Object>() |
| { |
| @Override |
| public void setAutoCommit(boolean autoCommit) |
| { |
| throw new UnsupportedOperationException(); |
| } |
| }; |
| |
| @ExcludeFromDump |
| private transient Map<String, CDOID> resourcePathCache = new HashMap<String, CDOID>(); |
| |
| @ExcludeFromDump |
| private transient CDOID lastLookupID; |
| |
| @ExcludeFromDump |
| private transient InternalCDOObject lastLookupObject; |
| |
| public AbstractCDOView(CDOBranchPoint branchPoint) |
| { |
| basicSetBranchPoint(branchPoint); |
| initObjectsMap(ReferenceType.SOFT); |
| } |
| |
| public AbstractCDOView() |
| { |
| initObjectsMap(ReferenceType.SOFT); |
| } |
| |
| public final IRegistry<String, Object> properties() |
| { |
| return properties; |
| } |
| |
| public String getRepositoryName() |
| { |
| Object repositoryName = properties.get(REPOSITORY_NAME_KEY); |
| if (repositoryName instanceof String) |
| { |
| return (String)repositoryName; |
| } |
| |
| return getSession().getRepositoryInfo().getName(); |
| } |
| |
| public void setRepositoryName(String repositoryName) |
| { |
| properties.put(REPOSITORY_NAME_KEY, repositoryName); |
| } |
| |
| public boolean isReadOnly() |
| { |
| return true; |
| } |
| |
| @Deprecated |
| public boolean isLegacyModeEnabled() |
| { |
| return true; |
| } |
| |
| protected synchronized final Map<CDOID, InternalCDOObject> getModifiableObjects() |
| { |
| return objects; |
| } |
| |
| public synchronized Map<CDOID, InternalCDOObject> getObjects() |
| { |
| if (objects == null) |
| { |
| return Collections.emptyMap(); |
| } |
| |
| return Collections.unmodifiableMap(objects); |
| } |
| |
| protected synchronized final void setObjects(Map<CDOID, InternalCDOObject> objects) |
| { |
| this.objects = objects; |
| } |
| |
| protected boolean initObjectsMap(ReferenceType referenceType) |
| { |
| ReferenceValueMap2<CDOID, InternalCDOObject> newObjects; |
| |
| switch (referenceType) |
| { |
| case STRONG: |
| { |
| if (objects instanceof ReferenceValueMap2.Strong<?, ?>) |
| { |
| return false; |
| } |
| |
| Map<CDOID, KeyedReference<CDOID, InternalCDOObject>> map = CDOIDUtil.createMap(); |
| newObjects = new ReferenceValueMap2.Strong<CDOID, InternalCDOObject>(map); |
| break; |
| } |
| |
| case SOFT: |
| { |
| if (objects instanceof ReferenceValueMap2.Soft<?, ?>) |
| { |
| return false; |
| } |
| |
| Map<CDOID, KeyedReference<CDOID, InternalCDOObject>> map = CDOIDUtil.createMap(); |
| newObjects = new ReferenceValueMap2.Soft<CDOID, InternalCDOObject>(map); |
| break; |
| } |
| |
| case WEAK: |
| { |
| if (objects instanceof ReferenceValueMap2.Weak<?, ?>) |
| { |
| return false; |
| } |
| |
| Map<CDOID, KeyedReference<CDOID, InternalCDOObject>> map = CDOIDUtil.createMap(); |
| newObjects = new ReferenceValueMap2.Weak<CDOID, InternalCDOObject>(map); |
| break; |
| } |
| |
| default: |
| throw new IllegalArgumentException(Messages.getString("CDOViewImpl.29")); //$NON-NLS-1$ |
| } |
| |
| if (objects == null) |
| { |
| setObjects(newObjects); |
| } |
| else |
| { |
| for (Entry<CDOID, InternalCDOObject> entry : objects.entrySet()) |
| { |
| InternalCDOObject object = entry.getValue(); |
| if (object != null) |
| { |
| newObjects.put(entry.getKey(), object); |
| } |
| } |
| |
| Map<CDOID, InternalCDOObject> oldObjects = objects; |
| setObjects(newObjects); |
| oldObjects.clear(); |
| } |
| |
| return true; |
| } |
| |
| public ViewAndState getViewAndState(CDOState state) |
| { |
| return viewAndStates[state.ordinal()]; |
| } |
| |
| public CDOStore getStore() |
| { |
| checkActive(); |
| return store; |
| } |
| |
| public ResourceSet getResourceSet() |
| { |
| return getViewSet().getResourceSet(); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public InternalCDOViewSet getViewSet() |
| { |
| return viewSet; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public void setViewSet(InternalCDOViewSet viewSet) |
| { |
| this.viewSet = viewSet; |
| if (viewSet != null) |
| { |
| viewSet.getResourceSet().getURIConverter().getURIHandlers().add(0, getURIHandler()); |
| } |
| } |
| |
| public CDOViewProvider getProvider() |
| { |
| return provider; |
| } |
| |
| public void setProvider(CDOViewProvider provider) |
| { |
| this.provider = provider; |
| } |
| |
| public synchronized CDOResourceImpl getRootResource() |
| { |
| checkActive(); |
| if (rootResource == null) |
| { |
| CDOID rootResourceID = getSession().getRepositoryInfo().getRootResourceID(); |
| if (rootResourceID == null || rootResourceID.isNull()) |
| { |
| throw new IllegalStateException("RootResourceID is null; is the repository not yet initialized?"); |
| } |
| |
| getObject(rootResourceID); |
| CheckUtil.checkState(rootResource, "rootResource"); |
| } |
| |
| return rootResource; |
| } |
| |
| private synchronized void setRootResource(CDOResourceImpl resource) |
| { |
| rootResource = resource; |
| rootResource.setRoot(true); |
| registerObject(rootResource); |
| |
| try |
| { |
| rootResource.load(null); |
| } |
| catch (IOException ex) |
| { |
| throw WrappedException.wrap(ex); |
| } |
| } |
| |
| @SuppressWarnings("deprecation") |
| public URI createResourceURI(String path) |
| { |
| if (provider != null) |
| { |
| URI uri = provider.getResourceURI(this, path); |
| if (uri != null) |
| { |
| return uri; |
| } |
| } |
| |
| InternalCDOSession session = getSession(); |
| return CDOURIUtil.createResourceURI(session, path); |
| } |
| |
| public synchronized boolean isEmpty() |
| { |
| CDOResource rootResource = getRootResource(); |
| if (rootResource.cdoPermission() == CDOPermission.NONE) |
| { |
| return true; |
| } |
| |
| boolean empty = rootResource.getContents().isEmpty(); |
| ensureContainerAdapter(rootResource); |
| return empty; |
| } |
| |
| public synchronized CDOResourceNode[] getElements() |
| { |
| CDOResource rootResource = getRootResource(); |
| EList<EObject> contents = rootResource.getContents(); |
| |
| List<CDOResourceNode> elements = new ArrayList<CDOResourceNode>(contents.size()); |
| for (EObject object : contents) |
| { |
| if (object instanceof CDOResourceNode) |
| { |
| CDOResourceNode element = (CDOResourceNode)object; |
| elements.add(element); |
| } |
| } |
| |
| ensureContainerAdapter(rootResource); |
| return elements.toArray(new CDOResourceNode[elements.size()]); |
| } |
| |
| private void ensureContainerAdapter(final CDOResource rootResource) |
| { |
| EList<Adapter> adapters = rootResource.eAdapters(); |
| ContainerAdapter adapter = getContainerAdapter(adapters); |
| if (adapter == null) |
| { |
| adapter = new ContainerAdapter(); |
| adapters.add(adapter); |
| |
| options().addChangeSubscriptionPolicy(new CDOAdapterPolicy() |
| { |
| public boolean isValid(EObject eObject, Adapter adapter) |
| { |
| return eObject == rootResource; |
| } |
| }); |
| } |
| } |
| |
| private ContainerAdapter getContainerAdapter(EList<Adapter> adapters) |
| { |
| for (Adapter adapter : adapters) |
| { |
| if (adapter instanceof ContainerAdapter && ((ContainerAdapter)adapter).getView() == this) |
| { |
| return (ContainerAdapter)adapter; |
| } |
| } |
| |
| return null; |
| } |
| |
| public CDOURIHandler getURIHandler() |
| { |
| return uriHandler; |
| } |
| |
| protected synchronized CDOBranchPoint getBranchPoint() |
| { |
| return branchPoint; |
| } |
| |
| protected synchronized CDOBranchPoint getNormalizedBranchPoint() |
| { |
| return normalizedBranchPoint; |
| } |
| |
| public synchronized boolean setBranch(CDOBranch branch) |
| { |
| return setBranchPoint(branch, getTimeStamp(), null); |
| } |
| |
| public synchronized boolean setBranch(CDOBranch branch, IProgressMonitor monitor) |
| { |
| return setBranchPoint(branch, getTimeStamp(), monitor); |
| } |
| |
| public synchronized boolean setTimeStamp(long timeStamp) |
| { |
| return setBranchPoint(getBranch(), timeStamp, null); |
| } |
| |
| public synchronized boolean setTimeStamp(long timeStamp, IProgressMonitor monitor) |
| { |
| return setBranchPoint(getBranch(), timeStamp, monitor); |
| } |
| |
| public synchronized boolean setBranchPoint(CDOBranch branch, long timeStamp) |
| { |
| return setBranchPoint(branch, timeStamp, null); |
| } |
| |
| public synchronized boolean setBranchPoint(CDOBranch branch, long timeStamp, IProgressMonitor monitor) |
| { |
| CDOBranchPoint branchPoint = branch.getPoint(timeStamp); |
| return setBranchPoint(branchPoint, monitor); |
| } |
| |
| public synchronized boolean setBranchPoint(CDOBranchPoint branchPoint) |
| { |
| return setBranchPoint(branchPoint, null); |
| } |
| |
| protected synchronized CDOBranchPoint basicSetBranchPoint(CDOBranchPoint branchPoint) |
| { |
| this.branchPoint = adjustBranchPoint(branchPoint); |
| normalizedBranchPoint = CDOBranchUtil.normalizeBranchPoint(this.branchPoint); |
| return this.branchPoint; |
| } |
| |
| protected final CDOBranchPoint adjustBranchPoint(CDOBranchPoint branchPoint) |
| { |
| CDOSession session = getSession(); |
| if (session != null) |
| { |
| CDOBranchManager branchManager = session.getBranchManager(); |
| branchPoint = CDOBranchUtil.adjustBranchPoint(branchPoint, branchManager); |
| } |
| |
| return CDOBranchUtil.copyBranchPoint(branchPoint); |
| } |
| |
| public void waitForUpdate(long updateTime) |
| { |
| waitForUpdate(updateTime, NO_TIMEOUT); |
| } |
| |
| public synchronized CDOBranch getBranch() |
| { |
| return branchPoint.getBranch(); |
| } |
| |
| public synchronized long getTimeStamp() |
| { |
| return branchPoint.getTimeStamp(); |
| } |
| |
| protected void fireViewTargetChangedEvent(CDOBranchPoint oldBranchPoint, IListener[] listeners) |
| { |
| fireEvent(new ViewTargetChangedEvent(oldBranchPoint, branchPoint), listeners); |
| } |
| |
| public boolean isDirty() |
| { |
| return false; |
| } |
| |
| public boolean hasConflict() |
| { |
| return false; |
| } |
| |
| public synchronized boolean hasResource(String path) |
| { |
| try |
| { |
| checkActive(); |
| getResourceNodeID(path); |
| return true; |
| } |
| catch (Exception ex) |
| { |
| return false; |
| } |
| } |
| |
| public synchronized CDOQueryImpl createQuery(String language, String queryString) |
| { |
| return createQuery(language, queryString, null); |
| } |
| |
| public synchronized CDOQueryImpl createQuery(String language, String queryString, Object context) |
| { |
| checkActive(); |
| return new CDOQueryImpl(this, language, queryString, context); |
| } |
| |
| public synchronized CDOResourceNode getResourceNode(String path) |
| { |
| CDOID id = getResourceNodeID(path); |
| if (id != null) // Should always be true |
| { |
| InternalCDOObject object = getObject(id); |
| if (object instanceof CDOResourceNode) |
| { |
| return (CDOResourceNode)object; |
| } |
| } |
| |
| throw new CDOException("Resource node not found: " + path); |
| } |
| |
| private CDOID getCachedResourceNodeID(String path) |
| { |
| if (resourcePathCache != null) |
| { |
| return resourcePathCache.get(path); |
| } |
| |
| return null; |
| } |
| |
| private void setCachedResourceNodeID(String path, CDOID id) |
| { |
| if (resourcePathCache != null) |
| { |
| if (id == null) |
| { |
| resourcePathCache.remove(path); |
| } |
| else |
| { |
| resourcePathCache.put(path, id); |
| } |
| } |
| } |
| |
| public synchronized void setResourcePathCache(Map<String, CDOID> resourcePathCache) |
| { |
| this.resourcePathCache = resourcePathCache; |
| } |
| |
| /** |
| * If <code>delta == null</code> the cache is cleared unconditionally. |
| * If <code>delta != null</code> the cache is cleared only if the delta can have an impact on the resource tree structure. |
| */ |
| public synchronized void clearResourcePathCacheIfNecessary(CDORevisionDelta delta) |
| { |
| if (resourcePathCache != null && !resourcePathCache.isEmpty()) |
| { |
| if (delta == null) |
| { |
| resourcePathCache.clear(); |
| } |
| else |
| { |
| CDOID rootResourceID = getSession().getRepositoryInfo().getRootResourceID(); |
| if (canHaveResourcePathImpact(delta, rootResourceID)) |
| { |
| resourcePathCache.clear(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * @return never <code>null</code> |
| */ |
| public synchronized CDOID getResourceNodeID(String path) |
| { |
| if (StringUtil.isEmpty(path)) |
| { |
| throw new IllegalArgumentException(Messages.getString("CDOViewImpl.1")); //$NON-NLS-1$ |
| } |
| |
| CDOID id = getCachedResourceNodeID(path); |
| if (id == null) |
| { |
| if (CDOURIUtil.SEGMENT_SEPARATOR.equals(path)) |
| { |
| id = getResourceNodeIDChecked(null, null); |
| setCachedResourceNodeID(path, id); |
| } |
| else |
| { |
| List<String> names = CDOURIUtil.analyzePath(path); |
| path = ""; |
| |
| for (String name : names) |
| { |
| path = path.length() == 0 ? name : path + "/" + name; |
| |
| CDOID cached = getCachedResourceNodeID(path); |
| if (cached != null) |
| { |
| id = cached; |
| } |
| else |
| { |
| id = getResourceNodeIDChecked(id, name); |
| setCachedResourceNodeID(path, id); |
| } |
| } |
| } |
| } |
| |
| return id; |
| } |
| |
| /** |
| * @return never <code>null</code> |
| */ |
| private CDOID getResourceNodeIDChecked(CDOID folderID, String name) |
| { |
| CDOID id = getResourceNodeID(folderID, name); |
| if (id == null) |
| { |
| throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.2"), name)); //$NON-NLS-1$ |
| } |
| |
| return id; |
| } |
| |
| /** |
| * @return never <code>null</code> |
| */ |
| protected synchronized CDOResourceNode getResourceNode(CDOID folderID, String name) |
| { |
| try |
| { |
| CDOID id = getResourceNodeID(folderID, name); |
| return (CDOResourceNode)getObject(id); |
| } |
| catch (CDOException ex) |
| { |
| throw ex; |
| } |
| catch (Exception ex) |
| { |
| throw new CDOException(ex); |
| } |
| } |
| |
| protected synchronized CDOID getResourceNodeID(CDOID folderID, String name) |
| { |
| if (folderID == null) |
| { |
| return getRootOrTopLevelResourceNodeID(name); |
| } |
| |
| if (name == null) |
| { |
| throw new IllegalArgumentException(Messages.getString("CDOViewImpl.3")); //$NON-NLS-1$ |
| } |
| |
| InternalCDORevision folderRevision = getLocalRevision(folderID); |
| EClass resourceFolderClass = EresourcePackage.eINSTANCE.getCDOResourceFolder(); |
| if (folderRevision.getEClass() != resourceFolderClass) |
| { |
| throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.4"), folderID)); //$NON-NLS-1$ |
| } |
| |
| EReference nodesFeature = EresourcePackage.eINSTANCE.getCDOResourceFolder_Nodes(); |
| EAttribute nameFeature = EresourcePackage.eINSTANCE.getCDOResourceNode_Name(); |
| |
| CDOList list; |
| boolean bypassPermissionChecks = folderRevision.bypassPermissionChecks(true); |
| |
| try |
| { |
| list = folderRevision.getList(nodesFeature); |
| } |
| finally |
| { |
| folderRevision.bypassPermissionChecks(bypassPermissionChecks); |
| } |
| |
| CDOStore store = getStore(); |
| int size = list.size(); |
| for (int i = 0; i < size; i++) |
| { |
| Object value = list.get(i); |
| value = store.resolveProxy(folderRevision, nodesFeature, i, value); |
| |
| CDOID childID = (CDOID)convertObjectToID(value); |
| InternalCDORevision childRevision = getLocalRevision(childID); |
| String childName = (String)childRevision.get(nameFeature, 0); |
| if (name.equals(childName)) |
| { |
| return childID; |
| } |
| } |
| |
| throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.5"), name)); //$NON-NLS-1$ |
| } |
| |
| protected synchronized CDOID getRootOrTopLevelResourceNodeID(String name) |
| { |
| if (name == null) |
| { |
| if (rootResource != null) |
| { |
| return rootResource.cdoID(); |
| } |
| |
| return getSession().getRepositoryInfo().getRootResourceID(); |
| } |
| |
| CDOQuery resourceQuery = createResourcesQuery(null, name, true); |
| resourceQuery.setMaxResults(1); |
| List<CDOID> ids = resourceQuery.getResult(CDOID.class); |
| if (ids.isEmpty()) |
| { |
| throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.7"), name)); //$NON-NLS-1$ |
| } |
| |
| if (ids.size() > 1) |
| { |
| // TODO is this still needed since the is resourceQuery.setMaxResults(1) ?? |
| throw new ImplementationError(Messages.getString("CDOViewImpl.8")); //$NON-NLS-1$ |
| } |
| |
| return ids.get(0); |
| } |
| |
| private InternalCDORevision getLocalRevision(CDOID id) |
| { |
| InternalCDORevision revision = null; |
| InternalCDOObject object = getObject(id, false); |
| if (object != null && object.cdoState() != CDOState.PROXY) |
| { |
| revision = object.cdoRevision(); |
| } |
| |
| if (revision == null) |
| { |
| revision = getRevision(id, true); |
| } |
| |
| if (revision == null) |
| { |
| throw new CDOException(MessageFormat.format(Messages.getString("CDOViewImpl.9"), id)); //$NON-NLS-1$ |
| } |
| |
| return revision; |
| } |
| |
| public synchronized List<InternalCDOObject> getObjectsList() |
| { |
| List<InternalCDOObject> result = new ArrayList<InternalCDOObject>(); |
| for (InternalCDOObject value : objects.values()) |
| { |
| if (value != null) |
| { |
| result.add(value); |
| } |
| } |
| |
| return result; |
| } |
| |
| public synchronized CDOResource getResource(String path) |
| { |
| return getResource(path, true); |
| } |
| |
| public synchronized CDOResource getResource(String path, boolean loadOnDemand) |
| { |
| checkActive(); |
| URI uri = CDOURIUtil.createResourceURI(this, path); |
| ResourceSet resourceSet = getResourceSet(); |
| ensureURIs(resourceSet); // Bug 337523 |
| |
| try |
| { |
| return (CDOResource)resourceSet.getResource(uri, loadOnDemand); |
| } |
| catch (RuntimeException ex) |
| { |
| EList<Resource> resources = resourceSet.getResources(); |
| for (int i = resources.size() - 1; i >= 0; --i) |
| { |
| Resource resource = resources.get(i); |
| if (uri.equals(resource.getURI())) |
| { |
| resources.remove(i); |
| break; |
| } |
| } |
| |
| throw ex; |
| } |
| } |
| |
| public CDOTextResource getTextResource(String path) |
| { |
| return (CDOTextResource)getResourceNode(path); |
| } |
| |
| public CDOBinaryResource getBinaryResource(String path) |
| { |
| return (CDOBinaryResource)getResourceNode(path); |
| } |
| |
| public CDOResourceFolder getResourceFolder(String path) |
| { |
| return (CDOResourceFolder)getResourceNode(path); |
| } |
| |
| /** |
| * Ensures that the URIs of all resources in this resourceSet, can be fetched without triggering the loading of |
| * additional resources. Without calling this first, it is dangerous to iterate over the resources to collect their |
| * URI's, because |
| */ |
| private void ensureURIs(ResourceSet resourceSet) |
| { |
| EList<Resource> resources = resourceSet.getResources(); |
| Resource[] resourceArr = null; |
| |
| int size = 0; |
| int i; |
| |
| do |
| { |
| i = size; |
| size = resources.size(); |
| if (size == 0) |
| { |
| break; |
| } |
| |
| if (resourceArr == null || resourceArr.length < size) |
| { |
| resourceArr = new Resource[size * 2]; |
| } |
| |
| resourceArr = resources.toArray(resourceArr); |
| for (; i < size; i++) |
| { |
| resourceArr[i].getURI(); |
| } |
| } while (resources.size() > size); |
| } |
| |
| public synchronized List<CDOResourceNode> queryResources(CDOResourceFolder folder, String name, boolean exactMatch) |
| { |
| CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch); |
| return resourceQuery.getResult(CDOResourceNode.class); |
| } |
| |
| public synchronized CloseableIterator<CDOResourceNode> queryResourcesAsync(CDOResourceFolder folder, String name, |
| boolean exactMatch) |
| { |
| CDOQuery resourceQuery = createResourcesQuery(folder, name, exactMatch); |
| return resourceQuery.getResultAsync(CDOResourceNode.class); |
| } |
| |
| private CDOQuery createResourcesQuery(CDOResourceFolder folder, String name, boolean exactMatch) |
| { |
| checkActive(); |
| CDOQueryImpl query = createQuery(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES, name); |
| query.setParameter(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES_FOLDER_ID, folder == null ? null : folder.cdoID()); |
| query.setParameter(CDOProtocolConstants.QUERY_LANGUAGE_RESOURCES_EXACT_MATCH, exactMatch); |
| return query; |
| } |
| |
| public <T extends EObject> List<T> queryInstances(EClass type) |
| { |
| CDOQuery query = createInstancesQuery(type); |
| return query.getResult(); |
| } |
| |
| public <T extends EObject> CloseableIterator<T> queryInstancesAsync(EClass type) |
| { |
| CDOQuery query = createInstancesQuery(type); |
| return query.getResultAsync(); |
| } |
| |
| private CDOQuery createInstancesQuery(EClass type) |
| { |
| CDOQuery query = createQuery(CDOProtocolConstants.QUERY_LANGUAGE_INSTANCES, null); |
| query.setParameter(CDOProtocolConstants.QUERY_LANGUAGE_INSTANCES_TYPE, type); |
| return query; |
| } |
| |
| public synchronized List<CDOObjectReference> queryXRefs(CDOObject targetObject, EReference... sourceReferences) |
| { |
| return queryXRefs(Collections.singleton(targetObject), sourceReferences); |
| } |
| |
| public synchronized List<CDOObjectReference> queryXRefs(Set<CDOObject> targetObjects, EReference... sourceReferences) |
| { |
| CDOQuery xrefsQuery = createXRefsQuery(targetObjects, sourceReferences); |
| return xrefsQuery.getResult(CDOObjectReference.class); |
| } |
| |
| public synchronized CloseableIterator<CDOObjectReference> queryXRefsAsync(Set<CDOObject> targetObjects, |
| EReference... sourceReferences) |
| { |
| CDOQuery xrefsQuery = createXRefsQuery(targetObjects, sourceReferences); |
| return xrefsQuery.getResultAsync(CDOObjectReference.class); |
| } |
| |
| private CDOQuery createXRefsQuery(Set<CDOObject> targetObjects, EReference... sourceReferences) |
| { |
| checkActive(); |
| |
| String string = createXRefsQueryString(targetObjects); |
| CDOQuery query = createQuery(CDOProtocolConstants.QUERY_LANGUAGE_XREFS, string); |
| |
| if (sourceReferences.length != 0) |
| { |
| string = createXRefsQueryParameter(sourceReferences); |
| query.setParameter(CDOProtocolConstants.QUERY_LANGUAGE_XREFS_SOURCE_REFERENCES, string); |
| } |
| |
| return query; |
| } |
| |
| private String createXRefsQueryString(Set<CDOObject> targetObjects) |
| { |
| StringBuilder builder = new StringBuilder(); |
| for (CDOObject target : targetObjects) |
| { |
| CDOID id = getXRefTargetID(target); |
| if (isObjectNew(id)) |
| { |
| throw new IllegalArgumentException("Cross referencing for uncommitted new objects not supported " + target); |
| } |
| |
| if (builder.length() != 0) |
| { |
| builder.append("|"); |
| } |
| |
| builder.append(id.isExternal() ? "e" : "i"); |
| builder.append(id.toURIFragment()); |
| |
| if (!(id instanceof CDOClassifierRef.Provider)) |
| { |
| builder.append("|"); |
| CDOClassifierRef classifierRef = new CDOClassifierRef(target.eClass()); |
| builder.append(classifierRef.getURI()); |
| } |
| } |
| |
| return builder.toString(); |
| } |
| |
| private String createXRefsQueryParameter(EReference[] sourceReferences) |
| { |
| StringBuilder builder = new StringBuilder(); |
| for (EReference sourceReference : sourceReferences) |
| { |
| if (builder.length() != 0) |
| { |
| builder.append("|"); |
| } |
| |
| CDOClassifierRef classifierRef = new CDOClassifierRef(sourceReference.getEContainingClass()); |
| builder.append(classifierRef.getURI()); |
| builder.append("|"); |
| builder.append(sourceReference.getName()); |
| } |
| |
| return builder.toString(); |
| } |
| |
| protected synchronized CDOID getXRefTargetID(CDOObject target) |
| { |
| if (FSMUtil.isTransient(target)) |
| { |
| throw new IllegalArgumentException("Cross referencing for transient objects not supported " + target); |
| } |
| |
| return target.cdoID(); |
| } |
| |
| public synchronized CDOResourceImpl getResource(CDOID resourceID) |
| { |
| if (CDOIDUtil.isNull(resourceID)) |
| { |
| throw new IllegalArgumentException("resourceID: " + resourceID); //$NON-NLS-1$ |
| } |
| |
| return (CDOResourceImpl)getObject(resourceID); |
| } |
| |
| public synchronized InternalCDOObject newInstance(EClass eClass) |
| { |
| EObject eObject = EcoreUtil.create(eClass); |
| return FSMUtil.adapt(eObject, this); |
| } |
| |
| public synchronized InternalCDORevision getRevision(CDOID id) |
| { |
| return getRevision(id, true); |
| } |
| |
| public synchronized InternalCDOObject getObject(CDOID id) |
| { |
| return getObject(id, true); |
| } |
| |
| public synchronized InternalCDOObject getObject(CDOID id, boolean loadOnDemand) |
| { |
| checkActive(); |
| if (CDOIDUtil.isNull(id)) |
| { |
| return null; |
| } |
| |
| if (rootResource != null && rootResource.cdoID() == id) |
| { |
| return rootResource; |
| } |
| |
| if (id == lastLookupID) |
| { |
| return lastLookupObject; |
| } |
| |
| lastLookupID = null; |
| lastLookupObject = null; |
| InternalCDOObject localLookupObject = null; |
| |
| if (id.isExternal()) |
| { |
| URI uri = URI.createURI(((CDOIDExternal)id).getURI()); |
| ResourceSet resourceSet = getResourceSet(); |
| |
| localLookupObject = (InternalCDOObject)CDOUtil.getCDOObject(resourceSet.getEObject(uri, loadOnDemand)); |
| if (localLookupObject == null) |
| { |
| if (!loadOnDemand) |
| { |
| return null; |
| } |
| |
| throw new ObjectNotFoundException(id, this); |
| } |
| } |
| else |
| { |
| // Needed for recursive call to getObject. (from createObject/cleanObject/getResource/getObject) |
| localLookupObject = objects.get(id); |
| if (localLookupObject == null) |
| { |
| if (!loadOnDemand) |
| { |
| return null; |
| } |
| |
| excludeNewObject(id); |
| localLookupObject = createObject(id); |
| |
| if (id == getSession().getRepositoryInfo().getRootResourceID()) |
| { |
| setRootResource((CDOResourceImpl)localLookupObject); |
| } |
| } |
| } |
| |
| lastLookupID = id; |
| lastLookupObject = localLookupObject; |
| return lastLookupObject; |
| } |
| |
| protected synchronized void excludeNewObject(CDOID id) |
| { |
| if (isObjectNew(id)) |
| { |
| throw new ObjectNotFoundException(id, this); |
| } |
| } |
| |
| public boolean isObjectNew(CDOID id) |
| { |
| return id.isTemporary(); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public synchronized <T extends EObject> T getObject(T objectFromDifferentView) |
| { |
| checkActive(); |
| CDOObject object = CDOUtil.getCDOObject(objectFromDifferentView); |
| CDOView view = object.cdoView(); |
| if (view == null) |
| { |
| return null; |
| } |
| |
| if (view != this) |
| { |
| if (!view.getSession().getRepositoryInfo().getUUID().equals(getSession().getRepositoryInfo().getUUID())) |
| { |
| throw new IllegalArgumentException( |
| MessageFormat.format(Messages.getString("CDOViewImpl.11"), objectFromDifferentView)); //$NON-NLS-1$ |
| } |
| |
| CDOID id = object.cdoID(); |
| InternalCDOObject contextified = getObject(id, true); |
| |
| if (objectFromDifferentView instanceof CDOLegacyAdapter) |
| { |
| @SuppressWarnings("unchecked") |
| T cast = (T)contextified; |
| return cast; |
| } |
| |
| @SuppressWarnings("unchecked") |
| T cast = (T)CDOUtil.getEObject(contextified); |
| return cast; |
| } |
| |
| return objectFromDifferentView; |
| } |
| |
| public synchronized boolean isObjectRegistered(CDOID id) |
| { |
| checkActive(); |
| if (CDOIDUtil.isNull(id)) |
| { |
| return false; |
| } |
| |
| return objects.containsKey(id); |
| } |
| |
| public synchronized InternalCDOObject removeObject(CDOID id) |
| { |
| if (id == null) |
| { |
| return null; |
| } |
| |
| if (id == lastLookupID) |
| { |
| lastLookupID = null; |
| lastLookupObject = null; |
| } |
| |
| return objects.remove(id); |
| } |
| |
| /** |
| * @return Never <code>null</code> |
| */ |
| private InternalCDOObject createObject(CDOID id) |
| { |
| if (TRACER.isEnabled()) |
| { |
| TRACER.trace("Creating object for " + id); //$NON-NLS-1$ |
| } |
| |
| InternalCDORevision revision = getRevision(id, true); |
| if (revision == null) |
| { |
| throw new ObjectNotFoundException(id, this); |
| } |
| |
| EClass eClass = revision.getEClass(); |
| InternalCDOObject object; |
| if (CDOModelUtil.isResource(eClass) && id != getSession().getRepositoryInfo().getRootResourceID()) |
| { |
| object = (InternalCDOObject)newResourceInstance(revision); |
| // object is PROXY |
| } |
| else |
| { |
| object = newInstance(eClass); |
| // object is TRANSIENT |
| } |
| |
| cleanObject(object, revision); |
| CDOStateMachine.INSTANCE.dispatchLoadNotification(object); |
| |
| // Bug 435198: Have object's resource added to the ResourceSet on call to CDOView.getObject(CDOID) |
| if (!CDOModelUtil.isResource(eClass)) |
| { |
| getStore().getResource(object); |
| } |
| |
| return object; |
| } |
| |
| private CDOResource newResourceInstance(InternalCDORevision revision) |
| { |
| String path = getResourcePath(revision); |
| URI uri = CDOURIUtil.createResourceURI(this, path); |
| |
| // Bug 334995: Check if locally there is already a resource with the same URI |
| ResourceSet resourceSet = getResourceSet(); |
| CDOResource resource1 = (CDOResource)resourceSet.getResource(uri, false); |
| |
| String oldName = null; |
| if (resource1 != null && !isReadOnly()) |
| { |
| // We have no other option than to change the name of the local resource |
| oldName = resource1.getName(); |
| resource1.setName(oldName + ".renamed"); |
| OM.LOG.warn("URI clash: resource being instantiated had same URI as a resource already present " |
| + "locally; local resource was renamed from " + oldName + " to " + resource1.getName()); |
| } |
| |
| CDOResource resource2 = getResource(path, true); |
| return resource2; |
| } |
| |
| private String getResourcePath(InternalCDORevision revision) |
| { |
| CDORevisionData data = revision.data(); |
| CDOID folderID; |
| |
| Object containerID = data.getContainerID(); |
| if (containerID instanceof CDOWithID) |
| { |
| folderID = ((CDOWithID)containerID).cdoID(); |
| } |
| else |
| { |
| folderID = (CDOID)containerID; |
| } |
| |
| String name = (String)revision.data().get(EresourcePackage.Literals.CDO_RESOURCE_NODE__NAME, 0); |
| if (CDOIDUtil.isNull(folderID)) |
| { |
| if (name == null) |
| { |
| return CDOURIUtil.SEGMENT_SEPARATOR; |
| } |
| |
| return name; |
| } |
| |
| InternalCDOObject object = getObject(folderID, true); |
| if (object instanceof CDOResourceFolder) |
| { |
| CDOResourceFolder folder = (CDOResourceFolder)object; |
| String path = folder.getPath(); |
| return path + CDOURIUtil.SEGMENT_SEPARATOR + name; |
| } |
| |
| throw new ImplementationError(MessageFormat.format(Messages.getString("CDOViewImpl.14"), object)); //$NON-NLS-1$ |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| protected synchronized void cleanObject(InternalCDOObject object, InternalCDORevision revision) |
| { |
| object.cdoInternalSetView(this); |
| object.cdoInternalSetRevision(revision); |
| |
| // Before setting the state to CLEAN (that can trigger a duplicate loading and instantiation of the current object) |
| // we make sure that object is registered - without throwing exception if it is already the case |
| registerObjectIfNotRegistered(object); |
| |
| object.cdoInternalSetState(CDOState.CLEAN); |
| object.cdoInternalPostLoad(); |
| } |
| |
| public synchronized CDOID provideCDOID(Object idOrObject) |
| { |
| Object shouldBeCDOID = convertObjectToID(idOrObject); |
| if (shouldBeCDOID instanceof CDOID) |
| { |
| CDOID id = (CDOID)shouldBeCDOID; |
| if (TRACER.isEnabled() && id != idOrObject) |
| { |
| TRACER.format("Converted object to CDOID: {0} --> {1}", idOrObject, id); //$NON-NLS-1$ |
| } |
| |
| return id; |
| } |
| |
| if (idOrObject instanceof InternalEObject) |
| { |
| InternalEObject eObject = (InternalEObject)idOrObject; |
| if (eObject instanceof InternalCDOObject) |
| { |
| InternalCDOObject object = (InternalCDOObject)idOrObject; |
| if (object.cdoView() != null && FSMUtil.isNew(object)) |
| { |
| String uri = EcoreUtil.getURI(object.cdoInternalInstance()).toString(); |
| if (object.cdoID().isTemporary()) |
| { |
| return CDOIDUtil.createTempObjectExternal(uri); |
| } |
| } |
| } |
| |
| Resource eResource = eObject.eResource(); |
| if (eResource != null) |
| { |
| // Check if eObject is contained by a deleted resource |
| if (!(eResource instanceof CDOResource) || ((CDOResource)eResource).cdoState() != CDOState.TRANSIENT) |
| { |
| String uri = EcoreUtil.getURI(CDOUtil.getEObject(eObject)).toString(); |
| return CDOIDUtil.createExternal(uri); |
| } |
| } |
| |
| throw new DanglingReferenceException(eObject); |
| } |
| |
| throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.16"), idOrObject)); //$NON-NLS-1$ |
| } |
| |
| public synchronized Object convertObjectToID(Object potentialObject) |
| { |
| return convertObjectToID(potentialObject, false); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public synchronized Object convertObjectToID(Object potentialObject, boolean onlyPersistedID) |
| { |
| if (potentialObject instanceof CDOID) |
| { |
| return potentialObject; |
| } |
| |
| if (potentialObject instanceof InternalEObject) |
| { |
| if (potentialObject instanceof InternalCDOObject) |
| { |
| InternalCDOObject object = (InternalCDOObject)potentialObject; |
| CDOID id = getID(object, onlyPersistedID); |
| if (id != null) |
| { |
| return id; |
| } |
| } |
| else |
| { |
| InternalCDOObject object = (InternalCDOObject)EcoreUtil |
| .getAdapter(((InternalEObject)potentialObject).eAdapters(), CDOLegacyAdapter.class); |
| if (object != null) |
| { |
| CDOID id = getID(object, onlyPersistedID); |
| if (id != null) |
| { |
| return id; |
| } |
| |
| potentialObject = object; |
| } |
| } |
| } |
| |
| return potentialObject; |
| } |
| |
| protected synchronized CDOID getID(InternalCDOObject object, boolean onlyPersistedID) |
| { |
| if (onlyPersistedID) |
| { |
| if (FSMUtil.isTransient(object) || FSMUtil.isNew(object)) |
| { |
| return null; |
| } |
| } |
| |
| CDOView view = object.cdoView(); |
| if (view == this) |
| { |
| return object.cdoID(); |
| } |
| |
| if (view != null && view.getSession() == getSession()) |
| { |
| boolean sameTarget = view.getBranch() == getBranch() && view.getTimeStamp() == getTimeStamp(); |
| if (sameTarget) |
| { |
| return object.cdoID(); |
| } |
| |
| throw new IllegalArgumentException("Object " + object + " is managed by a view with different target: " + view); |
| } |
| |
| return null; |
| } |
| |
| public synchronized Object convertIDToObject(Object potentialID) |
| { |
| if (potentialID instanceof CDOID) |
| { |
| if (potentialID == CDOID.NULL) |
| { |
| return null; |
| } |
| |
| CDOID id = (CDOID)potentialID; |
| if (id.isExternal()) |
| { |
| return getResourceSet().getEObject(URI.createURI(id.toURIFragment()), true); |
| } |
| |
| InternalCDOObject result = getObject(id, true); |
| if (result == null) |
| { |
| throw new ImplementationError(MessageFormat.format(Messages.getString("CDOViewImpl.17"), id)); //$NON-NLS-1$ |
| } |
| |
| return result.cdoInternalInstance(); |
| } |
| |
| return potentialID; |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public synchronized void attachResource(CDOResourceImpl resource) |
| { |
| if (!resource.isExisting()) |
| { |
| throw new ReadOnlyException(MessageFormat.format(Messages.getString("CDOViewImpl.18"), this)); //$NON-NLS-1$ |
| } |
| |
| // ResourceSet.getResource(uri, true) was called!! |
| resource.cdoInternalSetView(this); |
| resource.cdoInternalSetState(CDOState.PROXY); |
| registerProxyResource2(resource); |
| } |
| |
| private synchronized void registerProxyResource2(CDOResourceImpl resource) |
| { |
| URI uri = resource.getURI(); |
| String path = CDOURIUtil.extractResourcePath(uri); |
| boolean isRoot = "/".equals(path); //$NON-NLS-1$ |
| |
| try |
| { |
| CDOID id; |
| if (isRoot) |
| { |
| id = getSession().getRepositoryInfo().getRootResourceID(); |
| } |
| else |
| { |
| id = getResourceNodeID(path); |
| } |
| |
| resource.cdoInternalSetID(id); |
| registerObject(resource); |
| if (isRoot) |
| { |
| resource.setRoot(true); |
| rootResource = resource; |
| } |
| } |
| catch (LifecycleException ex) |
| { |
| throw ex; |
| } |
| catch (Exception ex) |
| { |
| throw new InvalidURIException(uri, ex); |
| } |
| } |
| |
| /** |
| * @deprecated No longer supported. |
| */ |
| @Deprecated |
| public synchronized void registerProxyResource(CDOResourceImpl resource) |
| { |
| registerProxyResource2(resource); |
| } |
| |
| /** |
| * Does the same as {@link AbstractCDOView#registerObject(InternalCDOObject)}, but without |
| * throwing any exception if object is already registered (in that case it will simply do nothing). |
| * |
| * @param object the object to register |
| */ |
| private void registerObjectIfNotRegistered(InternalCDOObject object) |
| { |
| if (CDOModelUtil.isResource(object.eClass())) |
| { |
| return; |
| } |
| |
| if (objects.containsKey(object.cdoID())) |
| { |
| return; |
| } |
| |
| registerObject(object); |
| } |
| |
| public synchronized void registerObject(InternalCDOObject object) |
| { |
| if (TRACER.isEnabled()) |
| { |
| TRACER.format("Registering {0}", object); //$NON-NLS-1$ |
| } |
| |
| InternalCDOObject old = objects.put(object.cdoID(), object); |
| if (old != null) |
| { |
| if (old != object) |
| { |
| throw new IllegalStateException(MessageFormat.format(Messages.getString("CDOViewImpl.30"), object.cdoID())); //$NON-NLS-1$ |
| } |
| |
| if (TRACER.isEnabled()) |
| { |
| TRACER.format(Messages.getString("CDOViewImpl.20"), old); //$NON-NLS-1$ |
| } |
| } |
| } |
| |
| public synchronized void deregisterObject(InternalCDOObject object) |
| { |
| if (TRACER.isEnabled()) |
| { |
| TRACER.format("Deregistering {0}", object); //$NON-NLS-1$ |
| } |
| |
| removeObject(object.cdoID()); |
| } |
| |
| public synchronized void remapObject(CDOID oldID) |
| { |
| CDOID newID; |
| InternalCDOObject object = objects.remove(oldID); |
| newID = object.cdoID(); |
| |
| objects.put(newID, object); |
| |
| if (lastLookupID == oldID) |
| { |
| lastLookupID = null; |
| lastLookupObject = null; |
| } |
| |
| if (TRACER.isEnabled()) |
| { |
| TRACER.format("Remapping {0} --> {1}", oldID, newID); //$NON-NLS-1$ |
| } |
| } |
| |
| public void addObjectHandler(CDOObjectHandler handler) |
| { |
| objectHandlers.add(handler); |
| } |
| |
| public void removeObjectHandler(CDOObjectHandler handler) |
| { |
| objectHandlers.remove(handler); |
| } |
| |
| public CDOObjectHandler[] getObjectHandlers() |
| { |
| return objectHandlers.get(); |
| } |
| |
| public synchronized void handleObjectStateChanged(InternalCDOObject object, CDOState oldState, CDOState newState) |
| { |
| CDOObjectHandler[] handlers = getObjectHandlers(); |
| for (int i = 0; i < handlers.length; i++) |
| { |
| CDOObjectHandler handler = handlers[i]; |
| handler.objectStateChanged(this, object, oldState, newState); |
| } |
| } |
| |
| /* |
| * Synchronized through InvalidationRunner.run() |
| */ |
| protected Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> invalidate(List<CDORevisionKey> allChangedObjects, |
| List<CDOIDAndVersion> allDetachedObjects, List<CDORevisionDelta> deltas, |
| Map<CDOObject, CDORevisionDelta> revisionDeltas, Set<CDOObject> detachedObjects) |
| { |
| boolean hasConflictResolvers = this instanceof CDOTransaction |
| && ((CDOTransaction)this).options().getConflictResolvers().length != 0; |
| Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = null; |
| |
| // Bug 363355: manage detached objects before changed objects to avoid issue on eContainer |
| for (CDOIDAndVersion key : allDetachedObjects) |
| { |
| InternalCDOObject detachedObject = removeObject(key.getID()); |
| if (detachedObject != null) |
| { |
| Pair<CDORevision, CDORevisionDelta> oldInfo = Pair.create((CDORevision)detachedObject.cdoRevision(), |
| CDORevisionDelta.DETACHED); |
| // if (!isLocked(detachedObject)) |
| { |
| CDOStateMachine.INSTANCE.detachRemote(detachedObject); |
| } |
| |
| detachedObjects.add(detachedObject); |
| if (detachedObject.cdoConflict()) |
| { |
| if (conflicts == null) |
| { |
| conflicts = new HashMap<CDOObject, Pair<CDORevision, CDORevisionDelta>>(); |
| } |
| |
| conflicts.put(detachedObject, oldInfo); |
| } |
| } |
| } |
| |
| for (CDORevisionKey key : allChangedObjects) |
| { |
| CDORevisionDelta delta = null; |
| if (key instanceof CDORevisionDelta) |
| { |
| delta = (CDORevisionDelta)key; |
| // Copy the revision delta so that conflict resolvers can modify it. |
| if (hasConflictResolvers) |
| { |
| delta = new CDORevisionDeltaImpl(delta, true); |
| } |
| |
| deltas.add(delta); |
| } |
| |
| CDOObject changedObject = objects.get(key.getID()); |
| if (changedObject != null) |
| { |
| Pair<CDORevision, CDORevisionDelta> oldInfo = Pair.create(changedObject.cdoRevision(), delta); |
| // if (!isLocked(changedObject)) |
| { |
| CDOStateMachine.INSTANCE.invalidate((InternalCDOObject)changedObject, key); |
| } |
| |
| revisionDeltas.put(changedObject, delta); |
| if (changedObject.cdoConflict()) |
| { |
| if (conflicts == null) |
| { |
| conflicts = new HashMap<CDOObject, Pair<CDORevision, CDORevisionDelta>>(); |
| } |
| |
| conflicts.put(changedObject, oldInfo); |
| } |
| } |
| } |
| |
| return conflicts; |
| } |
| |
| /** |
| * Overridden by {@link CDOTransactionImpl#handleConflicts(long, Map, List)}. |
| */ |
| protected synchronized void handleConflicts(long lastUpdateTime, |
| Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts, List<CDORevisionDelta> deltas) |
| { |
| // Do nothing |
| } |
| |
| public void fireAdaptersNotifiedEvent(long timeStamp) |
| { |
| fireEvent(new AdaptersNotifiedEvent(timeStamp)); |
| } |
| |
| /** |
| * TODO For this method to be useable locks must be cached locally! |
| */ |
| @SuppressWarnings("unused") |
| private boolean isLocked(InternalCDOObject object) |
| { |
| if (object.cdoWriteLock().isLocked()) |
| { |
| return true; |
| } |
| |
| if (object.cdoReadLock().isLocked()) |
| { |
| return true; |
| } |
| |
| return false; |
| } |
| |
| @Deprecated |
| public synchronized int reload(CDOObject... objects) |
| { |
| Collection<InternalCDOObject> internalObjects; |
| if (objects != null && objects.length != 0) |
| { |
| internalObjects = new ArrayList<InternalCDOObject>(objects.length); |
| for (CDOObject object : objects) |
| { |
| if (object instanceof InternalCDOObject) |
| { |
| internalObjects.add((InternalCDOObject)object); |
| } |
| } |
| } |
| else |
| { |
| internalObjects = new ArrayList<InternalCDOObject>(this.objects.values()); |
| } |
| |
| int result = internalObjects.size(); |
| if (result != 0) |
| { |
| CDOStateMachine.INSTANCE.reload(internalObjects.toArray(new InternalCDOObject[result])); |
| } |
| |
| return result; |
| } |
| |
| public void close() |
| { |
| LifecycleUtil.deactivate(this, OMLogger.Level.DEBUG); |
| } |
| |
| /** |
| * @since 2.0 |
| */ |
| public boolean isClosed() |
| { |
| return !isActive(); |
| } |
| |
| @SuppressWarnings({ "unchecked", "rawtypes" }) |
| public Object getAdapter(Class adapter) |
| { |
| return AdapterUtil.adapt(this, adapter, false); |
| } |
| |
| @Override |
| public String toString() |
| { |
| if (!isActive()) |
| { |
| return super.toString(); |
| } |
| |
| StringBuilder builder = new StringBuilder(); |
| if (isReadOnly()) |
| { |
| builder.append("View"); |
| } |
| else |
| { |
| builder.append("Transaction"); |
| } |
| |
| builder.append(" "); //$NON-NLS-1$ |
| builder.append(getViewID()); |
| |
| if (branchPoint != null) |
| { |
| boolean brackets = false; |
| if (getSession().getRepositoryInfo().isSupportingBranches()) |
| { |
| brackets = true; |
| builder.append(" ["); //$NON-NLS-1$ |
| builder.append(branchPoint.getBranch().getPathName()); // Do not synchronize on this view! |
| } |
| |
| long timeStamp = branchPoint.getTimeStamp(); // Do not synchronize on this view! |
| if (timeStamp != CDOView.UNSPECIFIED_DATE) |
| { |
| if (brackets) |
| { |
| builder.append(", "); //$NON-NLS-1$ |
| } |
| else |
| { |
| builder.append(" ["); //$NON-NLS-1$ |
| brackets = true; |
| } |
| |
| builder.append(CDOCommonUtil.formatTimeStamp(timeStamp)); |
| } |
| |
| if (brackets) |
| { |
| builder.append("]"); //$NON-NLS-1$ |
| } |
| } |
| |
| return builder.toString(); |
| } |
| |
| protected String getClassName() |
| { |
| return "CDOView"; //$NON-NLS-1$ |
| } |
| |
| public boolean isAdapterForType(Object type) |
| { |
| return type instanceof ResourceSet; |
| } |
| |
| public org.eclipse.emf.common.notify.Notifier getTarget() |
| { |
| return getResourceSet(); |
| } |
| |
| public synchronized void collectViewedRevisions(Map<CDOID, InternalCDORevision> revisions) |
| { |
| for (InternalCDOObject object : objects.values()) |
| { |
| CDOState state = object.cdoState(); |
| if (state != CDOState.CLEAN && state != CDOState.DIRTY && state != CDOState.CONFLICT) |
| { |
| continue; |
| } |
| |
| CDOID id = object.cdoID(); |
| if (revisions.containsKey(id)) |
| { |
| continue; |
| } |
| |
| InternalCDORevision revision = getViewedRevision(object); |
| if (revision == null) |
| { |
| continue; |
| } |
| |
| revisions.put(id, revision); |
| } |
| } |
| |
| protected InternalCDORevision getViewedRevision(InternalCDOObject object) |
| { |
| return CDOStateMachine.INSTANCE.readNoLoad(object); |
| } |
| |
| public synchronized CDOChangeSetData compareRevisions(CDOBranchPoint source) |
| { |
| CDOSession session = getSession(); |
| return session.compareRevisions(source, this); |
| } |
| |
| @Override |
| public CDOCommitHistory getHistory() |
| { |
| CDOBranch branch = getBranch(); |
| CDOCommitInfoManager commitInfoManager = getSession().getCommitInfoManager(); |
| return commitInfoManager.getHistory(branch); |
| } |
| |
| @Override |
| protected CDOCommitHistory createHistory(CDOObject key) |
| { |
| return new CDOObjectHistoryImpl(key); |
| } |
| |
| @Override |
| protected void doActivate() throws Exception |
| { |
| super.doActivate(); |
| |
| if (branchPoint != null) |
| { |
| basicSetBranchPoint(branchPoint); |
| } |
| } |
| |
| @Override |
| protected void doDeactivate() throws Exception |
| { |
| if (viewSet != null && viewSet.getResourceSet() != null) |
| { |
| viewSet.getResourceSet().getURIConverter().getURIHandlers().remove(getURIHandler()); |
| } |
| |
| viewSet = null; |
| objects = null; |
| store = null; |
| resourcePathCache = null; |
| lastLookupID = null; |
| lastLookupObject = null; |
| super.doDeactivate(); |
| } |
| |
| public static boolean canHaveResourcePathImpact(CDORevisionDelta delta, CDOID rootResourceID) |
| { |
| EClass eClass = delta.getEClass(); |
| if (EresourcePackage.Literals.CDO_RESOURCE_NODE.isSuperTypeOf(eClass)) |
| { |
| if (delta.getFeatureDelta(EresourcePackage.Literals.CDO_RESOURCE_NODE__NAME) != null) |
| { |
| return true; |
| } |
| } |
| |
| if (eClass == EresourcePackage.Literals.CDO_RESOURCE_FOLDER) |
| { |
| CDOListFeatureDelta featureDelta = (CDOListFeatureDelta)delta |
| .getFeatureDelta(EresourcePackage.Literals.CDO_RESOURCE_FOLDER__NODES); |
| if (canHaveResourcePathImpact(featureDelta)) |
| { |
| return true; |
| } |
| } |
| |
| if (eClass == EresourcePackage.Literals.CDO_RESOURCE) |
| { |
| if (rootResourceID == delta.getID()) |
| { |
| CDOListFeatureDelta featureDelta = (CDOListFeatureDelta)delta |
| .getFeatureDelta(EresourcePackage.Literals.CDO_RESOURCE__CONTENTS); |
| if (canHaveResourcePathImpact(featureDelta)) |
| { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| private static boolean canHaveResourcePathImpact(CDOListFeatureDelta featureDelta) |
| { |
| if (featureDelta != null) |
| { |
| for (CDOFeatureDelta listChange : featureDelta.getListChanges()) |
| { |
| CDOFeatureDelta.Type type = listChange.getType(); |
| switch (type) |
| { |
| case REMOVE: |
| case CLEAR: |
| case SET: |
| case UNSET: |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| protected abstract class Event extends org.eclipse.net4j.util.event.Event implements CDOViewEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| public Event() |
| { |
| super(AbstractCDOView.this); |
| } |
| |
| @Override |
| public AbstractCDOView getSource() |
| { |
| return (AbstractCDOView)super.getSource(); |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class AdaptersNotifiedEvent extends Event implements CDOViewAdaptersNotifiedEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| private long timeStamp; |
| |
| public AdaptersNotifiedEvent(long timeStamp) |
| { |
| this.timeStamp = timeStamp; |
| } |
| |
| public long getTimeStamp() |
| { |
| return timeStamp; |
| } |
| |
| @Override |
| public String toString() |
| { |
| return "CDOViewAdaptersNotifiedEvent: " + timeStamp; //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * @author Victor Roldan Betancort |
| */ |
| private final class ViewTargetChangedEvent extends Event implements CDOViewTargetChangedEvent |
| { |
| private static final long serialVersionUID = 1L; |
| |
| private final CDOBranchPoint oldBranchPoint; |
| |
| private final CDOBranchPoint branchPoint; |
| |
| public ViewTargetChangedEvent(CDOBranchPoint oldBranchPoint, CDOBranchPoint branchPoint) |
| { |
| this.oldBranchPoint = CDOBranchUtil.copyBranchPoint(oldBranchPoint); |
| this.branchPoint = CDOBranchUtil.copyBranchPoint(branchPoint); |
| } |
| |
| @Override |
| public String toString() |
| { |
| return MessageFormat.format("CDOViewTargetChangedEvent: {0}", branchPoint); //$NON-NLS-1$ |
| } |
| |
| public CDOBranchPoint getOldBranchPoint() |
| { |
| return oldBranchPoint; |
| } |
| |
| public CDOBranchPoint getBranchPoint() |
| { |
| return branchPoint; |
| } |
| } |
| |
| /** |
| * @author Eike Stepper |
| */ |
| private final class ContainerAdapter extends AdapterImpl |
| { |
| public AbstractCDOView getView() |
| { |
| return AbstractCDOView.this; |
| } |
| |
| @Override |
| public void notifyChanged(Notification msg) |
| { |
| if (msg.isTouch()) |
| { |
| return; |
| } |
| |
| if (msg.getFeature() != EresourcePackage.Literals.CDO_RESOURCE__CONTENTS) |
| { |
| return; |
| } |
| |
| IListener[] listeners = getListeners(); |
| if (listeners.length == 0) |
| { |
| return; |
| } |
| |
| IContainerEvent<CDOResourceNode> event = null; |
| int eventType = msg.getEventType(); |
| switch (eventType) |
| { |
| case Notification.ADD: |
| event = new SingleDeltaContainerEvent<CDOResourceNode>(AbstractCDOView.this, (CDOResourceNode)msg.getNewValue(), |
| IContainerDelta.Kind.ADDED); |
| break; |
| |
| case Notification.ADD_MANY: |
| // TODO |
| break; |
| |
| case Notification.REMOVE: |
| event = new SingleDeltaContainerEvent<CDOResourceNode>(AbstractCDOView.this, (CDOResourceNode)msg.getOldValue(), |
| IContainerDelta.Kind.REMOVED); |
| break; |
| |
| case Notification.REMOVE_MANY: |
| // TODO |
| break; |
| |
| case Notification.UNSET: |
| // TODO |
| break; |
| |
| default: |
| break; |
| } |
| |
| if (event != null) |
| { |
| fireEvent(event, listeners); |
| } |
| } |
| } |
| } |