//------------------------------------------------------------------------------ // Copyright (c) 2005, 2006 IBM Corporation 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: // IBM Corporation - initial implementation //------------------------------------------------------------------------------ package org.eclipse.epf.persistence.util; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.filebuffers.FileBuffers; import org.eclipse.core.filebuffers.ITextFileBuffer; import org.eclipse.core.filebuffers.ITextFileBufferManager; import org.eclipse.core.filebuffers.LocationKind; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceStatus; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.resources.WorkspaceJob; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.emf.common.CommonPlugin; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.UniqueEList; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.epf.common.utils.ExtensionHelper; import org.eclipse.epf.common.utils.IMarkerAttributeContributer; import org.eclipse.epf.common.utils.StrUtil; import org.eclipse.epf.persistence.FileManager; import org.eclipse.epf.persistence.MultiFileResourceSetImpl; import org.eclipse.epf.persistence.MultiFileSaveUtil; import org.eclipse.epf.persistence.PersistencePlugin; import org.eclipse.epf.uma.ecore.IProxyResolutionListener; import org.eclipse.epf.uma.ecore.ResolveException; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.osgi.util.NLS; /** * Background job that manage markers for unresolved proxies * * @author Phong Nguyen Le * @since 1.0 */ public class UnresolvedProxyMarkerManager extends WorkspaceJob implements IProxyResolutionListener { private static final long DELAY = 200; public static final String MARKER_ID = PersistencePlugin.getDefault().getId() + ".unresolvedProxyMarker"; //$NON-NLS-1$ public static final String PROXY_URI = "proxyURI"; //$NON-NLS-1$ public static final String OWNER_GUID = "ownerGUID"; //$NON-NLS-1$ private static class ValidObject { boolean valid; Object object; /** * @param valid * @param object */ public ValidObject(Object object) { super(); this.object = object; valid = true; } } private Map<URI, Set<ResolveException>> uriToExceptionsMap; private List<ResolveException> exceptions; private Map<String, ValidObject> resourceGUIDToMarkersMap; private Map<String, Collection<ValidObject>> elementGUIToMarkersMap; private ResourceSet resourceSet; private boolean enabled = true; private List<Resource> resourcesToValidateMarkers; private boolean autoScheduled = true; public boolean ignoreNewException = false; public UnresolvedProxyMarkerManager(ResourceSet resourceSet) { super(PersistenceResources.unresolvedProxyLoggerJob_name); setPriority(Job.BUILD); this.resourceSet = resourceSet; // unresolvedResourceGUIDToMarkersMap = new HashMap(); uriToExceptionsMap = new HashMap<URI, Set<ResolveException>>(); exceptions = new ArrayList<ResolveException>(); resourceGUIDToMarkersMap = new HashMap<String, ValidObject>(); elementGUIToMarkersMap = new HashMap<String, Collection<ValidObject>>(); resourcesToValidateMarkers = new UniqueEList<Resource>(); } private IMarker findMarker(IFile file, String proxyURI, String ownerGUID, int start, int end) throws CoreException { IMarker[] markers = file.findMarkers(MARKER_ID, false, IResource.DEPTH_ZERO); for (int i = 0; i < markers.length; i++) { IMarker marker = markers[i]; if(proxyURI.equals(marker.getAttribute(PROXY_URI)) && marker.getAttribute(IMarker.CHAR_START, -1) == start && marker.getAttribute(IMarker.CHAR_END, -1) == end) { return marker; } } return null; } private IMarker findMarker(Collection<IMarker> markers, int start, int end) throws CoreException { for (IMarker marker : markers) { if(marker.getAttribute(IMarker.CHAR_START, -1) == start && marker.getAttribute(IMarker.CHAR_END, -1) == end) { return marker; } } return null; } private boolean addException(ResolveException re) { synchronized(exceptions) { URI uri = ((InternalEObject)re.getProxy()).eProxyURI(); Set<ResolveException> exceptions = uriToExceptionsMap.get(uri); if(exceptions == null) { exceptions = new HashSet<ResolveException>(); uriToExceptionsMap.put(uri, exceptions); } if(exceptions.add(re)) { this.exceptions.add(re); return true; } return false; } } /** * Document based character sequence. */ private static class DocumentCharSequence implements CharSequence { /** Document */ private IDocument fDocument; /** * Initialize with the sequence of characters in the given * document. * * @param document the document */ public DocumentCharSequence(IDocument document) { fDocument= document; } /* * @see java.lang.CharSequence#length() */ public int length() { return fDocument.getLength(); } /* * @see java.lang.CharSequence#charAt(int) */ public char charAt(int index) { try { return fDocument.getChar(index); } catch (BadLocationException x) { throw new IndexOutOfBoundsException(x.getLocalizedMessage()); } } /* * @see java.lang.CharSequence#subSequence(int, int) */ public CharSequence subSequence(int start, int end) { try { return fDocument.get(start, end - start); } catch (BadLocationException x) { throw new IndexOutOfBoundsException(x.getLocalizedMessage()); } } } private static class MarkersAndLocations { Collection<IMarker> markers; Collection<int[]> locations; } private void updateMarker(IMarker[] markers, Resource resource, IProgressMonitor monitor) { URI containerURI = resource.getURI(); IWorkspace workspace = ResourcesPlugin.getWorkspace(); IPath path = new Path(containerURI.toFileString()); IFile file = workspace.getRoot().getFileForLocation(path); if (file != null) { try { file.refreshLocal(IResource.DEPTH_ZERO, null); Map<String, MarkersAndLocations> proxyURIToMarkersAndLocationsMap = new HashMap<String, MarkersAndLocations>(); for (int i = 0; i < markers.length; i++) { IMarker marker = markers[i]; Object proxyURI = marker.getAttribute(PROXY_URI); if(proxyURI != null) { String proxyURIStr = proxyURI.toString(); MarkersAndLocations markersAndLocations = proxyURIToMarkersAndLocationsMap.get(proxyURIStr); if(markersAndLocations == null) { markersAndLocations = new MarkersAndLocations(); markersAndLocations.markers = new HashSet<IMarker>(); markersAndLocations.locations = new HashSet<int[]>(); proxyURIToMarkersAndLocationsMap.put(proxyURIStr, markersAndLocations); } markersAndLocations.markers.add(marker); } } // locate the text of unresolved URI in file // ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager(); try { manager.connect(path, LocationKind.LOCATION, monitor); ITextFileBuffer fileBuffer= manager.getTextFileBuffer(path, LocationKind.LOCATION); fileBuffer.requestSynchronizationContext(); fileBuffer.getDocument(); IDocument doc = fileBuffer.getDocument(); if(doc != null) { for (Map.Entry<String, MarkersAndLocations> entry : proxyURIToMarkersAndLocationsMap.entrySet()) { String proxyURI = entry.getKey(); Pattern pattern = PatternConstructor.createPattern(proxyURI, true, false); Matcher matcher = pattern.matcher(new DocumentCharSequence(doc)); while(matcher.find()) { int start = matcher.start(); int end = matcher.end(); if(start != end) { entry.getValue().locations.add(new int[] { start, end }); } } } } fileBuffer.releaseSynchronizationContext(); } finally { manager.disconnect(path, LocationKind.LOCATION, monitor); } // make sure that resolver is still in the open library by checking whether its resource // still belongs to a resource set // if(resource != null && resource.getResourceSet() != null) { for (MarkersAndLocations markersAndLocations : proxyURIToMarkersAndLocationsMap.values()) { process_entry: for (Iterator<int[]> iterator = markersAndLocations.locations.iterator(); iterator.hasNext();) { if(markersAndLocations.markers.isEmpty()) { break process_entry; } int[] loc = iterator.next(); int start = loc[0]; int end = loc[1]; IMarker marker = findMarker(markersAndLocations.markers, start, end); if(marker == null) { Iterator<IMarker> iter = markersAndLocations.markers.iterator(); marker = iter.next(); iter.remove(); marker.setAttribute(IMarker.CHAR_START, start); marker.setAttribute(IMarker.CHAR_END, end); } else { markersAndLocations.markers.remove(marker); } } if(!markersAndLocations.markers.isEmpty()) { // invalid markers, must be deleted // for (IMarker marker : markersAndLocations.markers) { if(marker.exists()) { try { marker.delete(); } catch(CoreException e) { PersistencePlugin.getDefault().getLogger().logError(e); } } } } } } } catch (CoreException ex) { PersistencePlugin.getDefault().getLogger().logError(ex); if (MultiFileSaveUtil.DEBUG) { ex.printStackTrace(); } } } } private void addMarker(ResolveException re, Resource resource, URI proxyURI, String errMsg, String ownerGUID, IProgressMonitor monitor) { URI containerURI = resource.getURI(); IWorkspace workspace = ResourcesPlugin.getWorkspace(); IPath path = new Path(containerURI.toFileString()); IFile file = workspace.getRoot().getFileForLocation(path); if (file != null) { String location = containerURI != null ? containerURI .toFileString() : StrUtil.EMPTY_STRING; try { file.refreshLocal(IResource.DEPTH_ZERO, null); IMarker marker = findMarker(file, proxyURI.toString(), ownerGUID, 0, 0); if (marker != null) { return; } createMarker(re, proxyURI, errMsg, ownerGUID, file, location, proxyURI.toString(), 0, 0); } catch (CoreException e) { IStatus status = e.getStatus(); int code; if(status instanceof IResourceStatus && ((code = ((IResourceStatus) status).getCode()) == IResourceStatus.MARKER_NOT_FOUND || code == IResourceStatus.RESOURCE_NOT_FOUND)) { // do nothing } else { PersistencePlugin.getDefault().getLogger().logError(e); if (MultiFileSaveUtil.DEBUG) { e.printStackTrace(); } } } } } private IMarker createMarker(ResolveException re, URI proxyURI, String errMsg, String ownerGUID, IFile file, String location, String proxyURIStr, int start, int end) throws CoreException { IMarker marker; marker = file.createMarker(MARKER_ID); marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); marker.setAttribute(IMarker.MESSAGE, errMsg); marker.setAttribute(IMarker.LOCATION, location); marker.setAttribute(IMarker.TRANSIENT, true); marker.setAttribute(IMarker.CHAR_START, start); marker.setAttribute(IMarker.CHAR_END, end); marker.setAttribute(PROXY_URI, proxyURIStr); marker.setAttribute(OWNER_GUID, ownerGUID); IMarkerAttributeContributer attAdder = ExtensionHelper.getMarkerAttributeContributer(); if (attAdder != null) { attAdder.addAddtionalAttributes(marker, re); } // cache marker to it can be found easily and deleted // cacheMarker(marker, proxyURI); return marker; } private void addMarker(ResolveException re, IProgressMonitor monitor) { InternalEObject proxy = (InternalEObject) re.getProxy(); URI containerURI = null; Resource resource = null; if(re.getResolver() != null) { resource = re.getResolver().eResource(); // make sure that resolver is still in the open library by checking whether its resource // still belongs to a resource set // // System.out.println("UnresolvedProxyMarkerManager.addMarker(): resourceSet=" + resource.getResourceSet().hashCode()); if(resource != null && resource.getResourceSet() != null) { containerURI = resource.getURI(); } } if (containerURI != null) { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IPath path = new Path(containerURI.toFileString()); IFile file = workspace.getRoot().getFileForLocation(path); if (file != null) { String errMsg; if (re.exception() != null && re.exception().getLocalizedMessage() != null && re.exception().getLocalizedMessage().trim().length() > 0) { errMsg = re.exception().getLocalizedMessage(); } else { errMsg = re.getMessage() == null ? NLS.bind(PersistenceResources.UnresolvedProxyMarkerManager_couldNotResolveProxy, proxy.eProxyURI()) : re .getMessage(); } addMarker(re, resource, proxy.eProxyURI(), errMsg, MultiFileSaveUtil.getGuid(re.getResolver()), monitor); } } } /** * @param marker * @param uri proxy uri */ private void cacheMarker(IMarker marker, URI uri) { synchronized(elementGUIToMarkersMap) { String resourceGUID = uri.authority(); if(resourceGUID != null) { ValidObject vo = (ValidObject) resourceGUIDToMarkersMap.get(resourceGUID); if(vo == null) { vo = new ValidObject(new HashSet<IMarker>()); resourceGUIDToMarkersMap.put(resourceGUID, vo); } Collection<IMarker> markers = (Collection<IMarker>) vo.object; markers.add(marker); } String elementGUID = uri.fragment(); Collection<ValidObject> markers = elementGUIToMarkersMap.get(elementGUID); if(markers == null) { markers = new HashSet<ValidObject>(); elementGUIToMarkersMap.put(elementGUID, markers); } markers.add(new ValidObject(marker)); } } public void clearAll() { boolean oldEnabled = enabled; try { enabled = false; cancel(); synchronized (exceptions) { uriToExceptionsMap.clear(); exceptions.clear(); } synchronized(elementGUIToMarkersMap) { if(!elementGUIToMarkersMap.isEmpty()) { for (Collection<ValidObject> markers : elementGUIToMarkersMap.values()) { for (ValidObject vo : markers) { IMarker marker = (IMarker) vo.object; try { if(marker.exists()) { marker.delete(); } } catch(Exception e) { CommonPlugin.INSTANCE.log(e); } } markers.clear(); } elementGUIToMarkersMap.clear(); resourceGUIDToMarkersMap.clear(); } } synchronized(resourcesToValidateMarkers) { resourcesToValidateMarkers.clear(); } } finally { enabled = oldEnabled; // System.out.println("UnresolvedProxyMarkerManager.clearAll(): end"); } } public boolean hasUnresolvedProxy() { return !elementGUIToMarkersMap.isEmpty(); } private ResolveException nextException() { synchronized(exceptions) { // synchronized: in order to atomically obtain and clear requests if(exceptions.isEmpty()) { return null; } else { ResolveException e = (ResolveException) this.exceptions.remove(0); URI uri = ((InternalEObject)e.getProxy()).eProxyURI(); Set<ResolveException> exceptions = uriToExceptionsMap.get(uri); if(exceptions != null) { exceptions.remove(e); if(exceptions.isEmpty()) { uriToExceptionsMap.remove(uri); } } return e; } } } private Resource nextResourceToValidateMarkers() { synchronized(resourcesToValidateMarkers) { if(resourcesToValidateMarkers.isEmpty()) { return null; } else { return (Resource) resourcesToValidateMarkers.remove(0); } } } private void yield() { try { Thread.sleep(10); } catch (InterruptedException e) { // } } /* (non-Javadoc) * @see org.eclipse.core.resources.WorkspaceJob#runInWorkspace(org.eclipse.core.runtime.IProgressMonitor) */ public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException { // System.out.println("UnresolvedProxyMarkerManager.runInWorkspace(): begin"); monitor.beginTask("Process unsolved references", IProgressMonitor.UNKNOWN); try { if(!enabled) return Status.OK_STATUS; try { // add markers // monitor.subTask("Creating problem markers..."); ResolveException re; while(!monitor.isCanceled() && (re = nextException()) != null) { try { addMarker(re, monitor); } catch(Exception e) { PersistencePlugin.getDefault().getLogger().logError(e); } yield(); } if(monitor.isCanceled()) { throw new OperationCanceledException(); } // remove invalid markers // monitor.subTask("Removing invalid markers..."); removeMarkers(monitor); yield(); // validate resource markers // Resource resource; while(!monitor.isCanceled() && (resource = nextResourceToValidateMarkers()) != null) { monitor.subTask(NLS.bind("Validating ''{0}''...", FileManager.toFileString(resource.getURI()))); doValidateMarkers(resource); yield(); } } catch(Exception e) { if(e instanceof OperationCanceledException) { return Status.CANCEL_STATUS; } PersistencePlugin.getDefault().getLogger().logError(e); } return Status.OK_STATUS; } finally { // System.out.println("UnresolvedProxyMarkerManager.runInWorkspace(): end"); monitor.done(); } } private boolean removeFromResourceGUIDToMarkersMap(String proxyURI, IMarker marker) { URI uri = URI.createURI(proxyURI); String resourceGUID = uri.authority(); if(resourceGUID != null) { ValidObject vo = (ValidObject) resourceGUIDToMarkersMap.get(resourceGUID); if(vo != null) { Collection markers = ((Collection)vo.object); boolean ret = markers.remove(marker); if(markers.isEmpty()) { resourceGUIDToMarkersMap.remove(resourceGUID); } return ret; } } return false; } private void removeFromElementGUIDToMarkersMap(String proxyURI, IMarker marker) { URI uri = URI.createURI(proxyURI); String elementGUID = uri.fragment(); if(elementGUID != null) { Collection<ValidObject> validObjects = elementGUIToMarkersMap.get(elementGUID); if(validObjects != null) { for (Iterator<ValidObject> iterator1 = validObjects.iterator(); iterator1 .hasNext();) { ValidObject vo1 = (ValidObject) iterator1.next(); if(vo1.object == marker) { iterator1.remove(); } } if(validObjects.isEmpty()) { elementGUIToMarkersMap.remove(elementGUID); } } } } private void removeMarkers(IProgressMonitor monitor) { synchronized(elementGUIToMarkersMap) { for (Collection<ValidObject> markers : elementGUIToMarkersMap.values()) { for (Iterator<ValidObject> iterator = markers.iterator(); iterator.hasNext();) { ValidObject vo = (ValidObject) iterator.next(); if(!vo.valid) { try { IMarker marker = (IMarker) vo.object; if(marker.exists()) { String proxyURI = (String) marker.getAttribute(PROXY_URI); marker.delete(); // remove this marker from resourceGUIToMarkersMap // removeFromResourceGUIDToMarkersMap(proxyURI, marker); } iterator.remove(); } catch (Exception e) { CommonPlugin.INSTANCE.log(e); } } } } for (Iterator<ValidObject> iter = resourceGUIDToMarkersMap.values().iterator(); iter.hasNext();) { ValidObject vo = (ValidObject) iter.next(); if(!vo.valid) { vo.valid = true; Collection<IMarker> markers = (Collection<IMarker>) vo.object; for (Iterator<IMarker> iterator = markers.iterator(); iterator.hasNext();) { IMarker marker; try { marker = (IMarker) iterator.next(); if(marker.exists()) { String proxyURIStr = (String) marker.getAttribute(PROXY_URI); URI proxyURI = URI.createURI(proxyURIStr); // proxy is in the same resource that is just loaded // try to get the object with this proxy URI without loading new resource // // EObject o = resourceSet.getEObject(proxyURI, false); String elementGUID = proxyURI.fragment(); EObject o = (EObject) ((MultiFileResourceSetImpl)resourceSet).getGuidToMethodElementMap().get(elementGUID); if(o != null && !o.eIsProxy()) { marker.delete(); iterator.remove(); // remove this marker from elementGUIToMarkersMap // removeFromElementGUIDToMarkersMap(proxyURIStr, marker); } } else { iterator.remove(); } } catch(Exception e) { CommonPlugin.INSTANCE.log(e); } } if(markers.isEmpty()) { iter.remove(); } } } } } public void setEnabled(boolean enabled) { this.enabled = enabled; } public boolean isEnabled() { return enabled; } /* (non-Javadoc) * @see org.eclipse.epf.uma.ecore.IProxyResolutionListener#notifyException(java.lang.Exception) */ public void notifyException(Exception e) { if(!enabled) return; if (isIgnoreNewException()) { return; } if(e instanceof ResolveException) { ResolveException re = (ResolveException) e; // URI uri = ((InternalEObject)re.getProxy()).eProxyURI(); // if("_2J4YoPTDEdmkpYARNN468A".equals(uri.fragment())) { // System.out.println(); // } if(addException(re) && autoScheduled) { start(); } } } public void setAutoScheduled(boolean b) { autoScheduled = b; } public boolean isAutoScheduled() { return autoScheduled; } @Override public boolean shouldSchedule() { return !exceptions.isEmpty() || !elementGUIToMarkersMap.isEmpty() || !resourceGUIDToMarkersMap.isEmpty(); } /** * Schedules this job if exceptions are available to log */ public boolean start() { if(!enabled) return false; schedule(DELAY); return true; } /* (non-Javadoc) * @see org.eclipse.epf.uma.ecore.IProxyResolutionListener#proxyResolved(java.lang.Object, java.lang.Object) */ public void proxyResolved(Object proxy, Object resolved) { if(!enabled) return; if(proxy instanceof InternalEObject) { URI uri = ((InternalEObject)proxy).eProxyURI(); // if("_2J4YoPTDEdmkpYARNN468A".equals(uri.fragment())) { // System.out.println(); // } // remove all exceptions for this URI // removeExceptions(uri); // invalidate all markers for this URI // if(invalidateMarkers(uri)) { start(); } } } /** * @param uri */ private boolean invalidateMarkers(URI uri) { synchronized(elementGUIToMarkersMap) { boolean ret = false; String resourceGUID = uri.authority(); if(resourceGUID != null) { ValidObject vo = (ValidObject) resourceGUIDToMarkersMap.get(resourceGUID); if(vo != null) { vo.valid = false; ret = true; } } String elementGUID = uri.fragment(); if(elementGUID != null) { Collection<ValidObject> markers = elementGUIToMarkersMap.get(elementGUID); if(markers != null && !markers.isEmpty()) { ret = true; for (ValidObject vo : markers) { vo.valid = false; } } } return ret; } } /** * @param uri */ private void removeExceptions(URI uri) { synchronized (exceptions) { Set<ResolveException> exceptions = uriToExceptionsMap.get(uri); if(exceptions == null || exceptions.isEmpty()) return; this.exceptions.removeAll(exceptions); uriToExceptionsMap.remove(uri); } } /** * Clears markers for unresolved proxies of the given resource * * @param resource */ public void clearMarkers(Resource resource) { try { IResource file = FileManager.getResourceForLocation(resource.getURI().toFileString()); if(file instanceof IFile) { IMarker[] markers = file.findMarkers(MARKER_ID, false, IResource.DEPTH_ZERO); for (int i = 0; i < markers.length; i++) { IMarker marker = markers[i]; removeMarker(marker); } } } catch(Exception e) { PersistencePlugin.getDefault().getLogger().logError(e); } } public void removeMarker(IMarker marker) { String proxyURI = null; try { if(marker.exists()) { proxyURI = (String) marker.getAttribute(PROXY_URI); marker.delete(); } } catch (Exception e) { PersistencePlugin.getDefault().getLogger().logError(e); } if(proxyURI != null) { synchronized(elementGUIToMarkersMap) { removeFromElementGUIDToMarkersMap(proxyURI, marker); removeFromResourceGUIDToMarkersMap(proxyURI, marker); } } } private static class MarkerInfo { String proxyURI; String ownerGUID; String message; /* (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ public boolean equals(Object obj) { if(obj instanceof MarkerInfo) { MarkerInfo info = (MarkerInfo) obj; if(proxyURI != null && ownerGUID != null && proxyURI.equals(info.proxyURI) && ownerGUID.equals(info.ownerGUID)) { return true; } } return super.equals(obj); } @Override public int hashCode() { int result = proxyURI.hashCode(); result ^= ownerGUID.hashCode(); result ^= message.hashCode(); return result; } } /** * Validates markers for unresolved proxies of the given resource * * @param resource */ public void validateMarkers(Resource resource) { boolean newlyAdded = false; synchronized(resourcesToValidateMarkers) { newlyAdded = resourcesToValidateMarkers.add(resource); } if(newlyAdded) { start(); } } public void validateAllMarkers() { boolean newlyAdded = false; boolean invalid = false; if(!elementGUIToMarkersMap.isEmpty()) { ArrayList<Collection<ValidObject>> validObjectCollections = null; synchronized (elementGUIToMarkersMap) { if(!elementGUIToMarkersMap.isEmpty()) { validObjectCollections = new ArrayList<Collection<ValidObject>>(); for (Collection<ValidObject> collection : elementGUIToMarkersMap.values()) { if(!collection.isEmpty()) { validObjectCollections.add(new ArrayList<ValidObject>(collection)); } } } } if(validObjectCollections != null) { synchronized(resourcesToValidateMarkers) { for (Collection<ValidObject> markers : validObjectCollections) { for (ValidObject vo : markers) { IMarker marker = (IMarker) vo.object; try { if(marker.exists()) { String location = (String)marker.getAttribute(IMarker.LOCATION); URI uri = URI.createFileURI(location); Resource resource = resourceSet.getResource(uri, true); newlyAdded = resourcesToValidateMarkers.add(resource) || newlyAdded; } else { vo.valid = false; invalid = true; } } catch (CoreException e) { PersistencePlugin.getDefault().getLogger().logError(e); } } } } } } if(newlyAdded) { start(); } else if(invalid) { removeMarkers(new NullProgressMonitor()); } } public void doValidateMarkers(Resource resource) { try { IResource file = FileManager.getResourceForLocation(resource.getURI().toFileString()); if(file instanceof IFile && file.exists()) { IMarker[] markers = file.findMarkers(MARKER_ID, false, IResource.DEPTH_ZERO); HashSet<IMarker> markersToUpdate = new HashSet<IMarker>(); for (int i = 0; i < markers.length; i++) { IMarker marker = markers[i]; String proxyURI = (String) marker.getAttribute(PROXY_URI); if(proxyURI != null) { URI uri = URI.createURI(proxyURI); // try to get the object with this proxy URI without loading new resource // String elementGUID = uri.fragment(); EObject o = (EObject) ((MultiFileResourceSetImpl)resourceSet).getGuidToMethodElementMap().get(elementGUID); if(o == null || o.eIsProxy()) { // marker still can exist, need to update it // markersToUpdate.add(marker); } else { // object is resolved, must delete marker // if(marker.exists()) { try { marker.delete(); } catch(Exception e) { PersistencePlugin.getDefault().getLogger().logError(e); } } synchronized(elementGUIToMarkersMap) { removeFromElementGUIDToMarkersMap(proxyURI, marker); removeFromResourceGUIDToMarkersMap(proxyURI, marker); } } } } if(!markersToUpdate.isEmpty()) { IMarker[] markerArray = new IMarker[markersToUpdate.size()]; markersToUpdate.toArray(markerArray); updateMarker(markerArray, resource, new NullProgressMonitor()); } } } catch(Exception e) { PersistencePlugin.getDefault().getLogger().logError(e); } } public boolean isIgnoreNewException() { return ignoreNewException; } public void setIgnoreNewException(boolean ignoreNewException) { this.ignoreNewException = ignoreNewException; } }