blob: b0f93e311eddda1e17aa076f5fa8b521d581690f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM - Initial API and implementation
*******************************************************************************/
package org.eclipse.core.tools.resources;
import java.util.*;
import org.eclipse.core.internal.resources.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.tools.*;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.osgi.util.NLS;
/**
* Constructs a tree made of <code>TreeContentProviderNode</code>, representing
* several details about resources.
* Details include:
* <ul>
* <li>resource's full path;</li>
* <li>content ID;</li>
* <li>node ID;</li>
* <li>resource type;</li>
* <li>local sync info;</li>
* <li>resource info flags;</li>
* <li>markers' type and attributes;</li>
* <li>sync info;</li>
* <li>session properties;</li>
* <li>persistent properties.</li>
* </ul>
*
* @see org.eclipse.core.tools.TreeContentProviderNode
*/
public class ResourceContentProvider extends AbstractTreeContentProvider {
/**
* The maximum number of bytes to be shown for sync info
*/
private final static int MAX_SYNC_INFO_BYTES = 8;
/**
* Collects resource info. Calls all other <code>extract...</code> methods.
*
* @param selectedResource the resource object from where to extract information
*/
protected void extractInfo(IResource selectedResource) {
if (!(selectedResource instanceof Resource)) {
String message = NLS.bind(Messages.resource_error_unknown_resource_impl, selectedResource.getClass().getName());
getRootNode().addChild(message);
return;
}
Resource resource = (Resource) selectedResource;
ResourceInfo info = resource.getResourceInfo(true, false);
// Resource#getResourceInfo may return null when the resource
// does not exist anymore. In this case, we just ignore it.
if (info == null)
return;
extractBasicInfo(resource, info);
extractFlags(info);
extractContentDescription(resource);
extractMarkersInfo(resource, info);
extractSyncInfo(info);
extractPersistentProperties(resource);
extractSessionProperties(resource);
}
/**
* Collects persistent properties information.
*
* @param resource the resource object from where to extract information
*/
protected void extractPersistentProperties(IResource resource) {
try {
Map<QualifiedName, String> properties = ((Workspace) ResourcesPlugin.getWorkspace()).getPropertyManager().getProperties(resource);
if (properties.isEmpty())
return;
// creates a node for persistent properties and populates it
TreeContentProviderNode propertiesRootNode = createNode(Messages.resource_persistent_properties);
getRootNode().addChild(propertiesRootNode);
for (Map.Entry<QualifiedName, String> entry : properties.entrySet()) {
propertiesRootNode.addChild(createNode(entry.getKey().toString(), entry.getValue()));
}
} catch (CoreException ce) {
getRootNode().addChild(createNode(NLS.bind(Messages.resource_error_stored_properties, ce.toString())));
}
}
/**
* Collects session properties information.
*
* @param resource the resource object from where to extract information
*/
protected void extractSessionProperties(IResource resource) {
// retrieves all session properties for the selected resource
Map<QualifiedName, Object> properties = org.eclipse.core.internal.resources.SpySupport.getSessionProperties(resource);
if (properties == null || properties.size() == 0)
return;
// creates a node for session properties and populates it
TreeContentProviderNode propertiesRootNode = createNode(Messages.resource_session_properties);
getRootNode().addChild(propertiesRootNode);
for (Map.Entry<QualifiedName, Object> entry : properties.entrySet()) {
propertiesRootNode.addChild(createNode(entry.getKey().toString(), entry.getValue()));
}
}
/**
* Extracts basic resource info.
*
* @param resource the resource object from where to extract information
* @param info the resource info object from where to extract information
*/
protected void extractBasicInfo(IResource resource, ResourceInfo info) {
// extracts information from IResource
IPath resourcePath = resource.getFullPath();
long id = info.getContentId();
String type = null;
switch (resource.getType()) {
case IResource.FILE :
type = Messages.resource_file;
break;
case IResource.FOLDER :
type = Messages.resource_folder;
break;
case IResource.PROJECT :
type = Messages.resource_project;
break;
case IResource.ROOT :
type = Messages.resource_root;
break;
}
// extracts information from ResourceInfo
long localSyncInfo = info.getLocalSyncInfo();
long nodeId = info.getNodeId();
// creates a root node for each basic information
getRootNode().addChild(createNode(Messages.resource_full_path, resourcePath));
getRootNode().addChild(createNode(Messages.resource_content_id, Long.toString(id)));
getRootNode().addChild(createNode(Messages.resource_type, type));
getRootNode().addChild(createNode(Messages.resource_node_id, Long.toString(nodeId)));
getRootNode().addChild(createNode(Messages.resource_local_sync_info, Long.toString(localSyncInfo)));
}
/**
* Extracts flags from the resource info object, building a 'Flags'
* subtree in the resource details' tree.
*
* @param info the resource info object from where to extract information
*/
protected void extractFlags(ResourceInfo info) {
// extract flags'values for the resource info object
boolean isOpen = info.isSet(ICoreConstants.M_OPEN);
boolean localExists = info.isSet(ICoreConstants.M_LOCAL_EXISTS);
boolean isPhantom = info.isSet(ICoreConstants.M_PHANTOM);
boolean isUsed = info.isSet(ICoreConstants.M_USED);
boolean isDerived = info.isSet(ICoreConstants.M_DERIVED);
boolean isTeamPrivateMember = info.isSet(ICoreConstants.M_TEAM_PRIVATE_MEMBER);
boolean isMarkersSnapDirty = info.isSet(ICoreConstants.M_MARKERS_SNAP_DIRTY);
boolean isSyncInfoSnapDirty = info.isSet(ICoreConstants.M_SYNCINFO_SNAP_DIRTY);
boolean noContentDescription = info.isSet(ICoreConstants.M_NO_CONTENT_DESCRIPTION);
boolean defaultContentDescription = info.isSet(ICoreConstants.M_DEFAULT_CONTENT_DESCRIPTION);
boolean isHidden = info.isSet(ICoreConstants.M_HIDDEN);
// creates a node for flags
TreeContentProviderNode flagsParentNode = createNode(Messages.resource_flags);
getRootNode().addChild(flagsParentNode);
// creates a child node in "Flags" node for each basic information
flagsParentNode.addChild(createNode(Messages.resource_open, Boolean.valueOf(isOpen)));
flagsParentNode.addChild(createNode(Messages.resource_local_exists, Boolean.valueOf(localExists)));
flagsParentNode.addChild(createNode(Messages.resource_phantom, Boolean.valueOf(isPhantom)));
flagsParentNode.addChild(createNode(Messages.resource_used, Boolean.valueOf(isUsed)));
flagsParentNode.addChild(createNode(Messages.resource_derived, Boolean.valueOf(isDerived)));
flagsParentNode.addChild(createNode(Messages.resource_team_private, Boolean.valueOf(isTeamPrivateMember)));
flagsParentNode.addChild(createNode(Messages.resource_markers_snap_dirty, Boolean.valueOf(isMarkersSnapDirty)));
flagsParentNode.addChild(createNode(Messages.resource_sync_info_snap_dirty, Boolean.valueOf(isSyncInfoSnapDirty)));
flagsParentNode.addChild(createNode(Messages.resource_no_content_description, Boolean.valueOf(noContentDescription)));
flagsParentNode.addChild(createNode(Messages.resource_default_content_description, Boolean.valueOf(defaultContentDescription)));
flagsParentNode.addChild(createNode(Messages.resource_hidden, Boolean.valueOf(isHidden)));
}
protected void extractContentDescription(Resource resource) {
if (resource.getType() != IResource.FILE)
return;
File file = (File) resource;
// creates a node for flags
try {
boolean cached = org.eclipse.core.internal.resources.SpySupport.isContentDescriptionCached(file);
String description = file.getContentDescription() + " (" + NLS.bind(Messages.resource_content_description_from_cache, Boolean.toString(cached)) + ")"; //$NON-NLS-1$//$NON-NLS-2$
TreeContentProviderNode contentDescriptionNode = createNode(Messages.resource_content_description, description);
getRootNode().addChild(contentDescriptionNode);
} catch (CoreException ce) {
// in the case of a CoreException, just present it as node
getRootNode().addChild(createNode(NLS.bind(Messages.resource_error_content_description, ce.toString())));
}
}
/**
* Extracts from resource info object all information regarding markers,
* building a 'Markers' subtree in the resource details tree.
*
* @param resource the resource object from where to extract information
* @param info the resource info object from where to extract information
*/
protected void extractMarkersInfo(IResource resource, ResourceInfo info) {
MarkerSet markerSet = info.getMarkers();
if (markerSet == null)
return;
IMarkerSetElement[] markerSetElements = markerSet.elements();
if (markerSetElements.length == 0)
return;
// creates a root node for all markers
TreeContentProviderNode markersParentNode = createNode(Messages.resource_markers);
getRootNode().addChild(markersParentNode);
int markerSetSize = markerSetElements.length;
for (int i = 0; i < markerSetSize; i++) {
try {
long markerID = markerSetElements[i].getId();
IMarker marker = resource.getMarker(markerID);
// creates a marker node
String id = " [id = " + marker.getId() + "]"; //$NON-NLS-1$//$NON-NLS-2$
TreeContentProviderNode markerNode = createNode(marker.getType() + id);
markersParentNode.addChild(markerNode);
extractMarkerAttributes(markerNode, marker);
} catch (CoreException ce) {
// in the case of a CoreException, just present it as node
markersParentNode.addChild(createNode(NLS.bind(Messages.resource_error_marker, ce.toString())));
}
}
}
/**
* Retrieves all attributes from a marker, adding them as sub-nodes in the
* marker's node.
*
* @param markerNode the marker's node
* @param marker the marker object
* @throws CoreException if this method fails. Reasons include:
* <ul>
* <li>This marker does not exist.</li>
* </ul>
*/
protected void extractMarkerAttributes(TreeContentProviderNode markerNode, IMarker marker) throws CoreException {
Map<String, Object> attributes = marker.getAttributes();
if (attributes == null || attributes.size() == 0)
return;
// create a node (under markerNode) for each attribute found
for (Map.Entry<String, Object> mapEntry : attributes.entrySet()) {
String attributeName = mapEntry.getKey();
Object attributeValue = mapEntry.getValue();
// adds each attribute as a subnode under
// this marker's node
markerNode.addChild(createNode(attributeName, attributeValue));
}
// attributes will be ordered by attribute name
markerNode.sort();
}
/**
* Extracts from the resource info object all information related to VCM,
* building a 'Sync Info' subtree in the resource details tree.
*
* @param info the resource info object from where to extract information
*/
protected void extractSyncInfo(ResourceInfo info) {
Map<QualifiedName, Object> syncInfo = info.getSyncInfo(true);
if (syncInfo == null || syncInfo.isEmpty())
return;
// creates a root node for all sync info
TreeContentProviderNode syncInfoParentNode = createNode(Messages.resource_sync_info);
getRootNode().addChild(syncInfoParentNode);
for (Map.Entry<QualifiedName, Object> entry : syncInfo.entrySet()) {
// creates a sync info node
String name = entry.getKey().toString();
String value = ByteUtil.byteArrayToString((byte[]) entry.getValue(), MAX_SYNC_INFO_BYTES);
syncInfoParentNode.addChild(createNode(name, value));
}
}
/**
* Reconstructs this content provider data model upon the provided input object.
*
* @param input the new input object - must not be null
*/
@Override
protected void rebuild(Viewer viewer, final Object input) {
SafeRunner.run(new SafeRunnable() {
@Override
public void run() throws Exception {
extractInfo((IResource) input);
}
});
}
/**
* Returns true if the input is a resource.
*
* @param input an input object
* @see org.eclipse.core.tools.AbstractTreeContentProvider#acceptInput(java.lang.Object)
*/
@Override
protected boolean acceptInput(Object input) {
return input instanceof IResource;
}
}