PowerShell/src/Microsoft.PowerShell.Commands.Management/commands/management/ParsePathCommand.cs
PowerShell Team c748652c34 Copy all mapped files from [SD:725290]
commit 8cec8f150da7583b7af5efbe2853efee0179750c
2016-07-28 23:23:03 -07:00

569 lines
20 KiB
C#

/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Management.Automation;
using System.Management.Automation.Internal;
using Dbg = System.Management.Automation;
namespace Microsoft.PowerShell.Commands
{
/// <summary>
/// A command to resolve MSH paths containing glob characters to
/// MSH paths that match the glob strings.
/// </summary>
[Cmdlet("Split", "Path", DefaultParameterSetName = "ParentSet", SupportsTransactions = true, HelpUri = "http://go.microsoft.com/fwlink/?LinkID=113404")]
[OutputType(typeof(string), ParameterSetName = new string[] { SplitPathCommand.leafSet,
SplitPathCommand.noQualifierSet,
SplitPathCommand.parentSet,
SplitPathCommand.qualifierSet,
SplitPathCommand.literalPathSet})]
[OutputType(typeof(bool), ParameterSetName = new string[] { SplitPathCommand.isAbsoluteSet })]
public class SplitPathCommand : CoreCommandWithCredentialsBase
{
#region Parameters
/// <summary>
/// The parameter set name to get the parent path
/// </summary>
private const string parentSet = "ParentSet";
/// <summary>
/// The parameter set name to get the leaf name
/// </summary>
private const string leafSet = "LeafSet";
/// <summary>
/// The parameter set name to get the qualifier set.
/// </summary>
private const string qualifierSet = "QualifierSet";
/// <summary>
/// The parameter set name to get the noqualifier set.
/// </summary>
private const string noQualifierSet = "NoQualifierSet";
/// <summary>
/// The parameter set name to get the IsAbsolute set.
/// </summary>
private const string isAbsoluteSet = "IsAbsoluteSet";
/// <summary>
/// The parameter set name to get the LiteralPath set.
/// </summary>
private const string literalPathSet = "LiteralPathSet";
/// <summary>
/// Gets or sets the path parameter to the command
/// </summary>
[Parameter(Position = 0, ParameterSetName = parentSet, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0, ParameterSetName = leafSet, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0, ParameterSetName = qualifierSet, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0, ParameterSetName = noQualifierSet, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
[Parameter(Position = 0, ParameterSetName = isAbsoluteSet, Mandatory = true, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true)]
public string[] Path
{
get
{
return paths;
} // get
set
{
paths = value;
} // set
} // Path
/// <summary>
/// Gets or sets the literal path parameter to the command
/// </summary>
[Parameter(ParameterSetName = "LiteralPathSet", Mandatory = true, ValueFromPipeline = false, ValueFromPipelineByPropertyName = true)]
[Alias("PSPath")]
public string[] LiteralPath
{
get
{
return paths;
} // get
set
{
base.SuppressWildcardExpansion = true;
paths = value;
} // set
} // LiteralPath
/// <summary>
/// Determines if the qualifier should be returned
/// </summary>
///
/// <value>
/// If true the qualifier of the path will be returned.
/// The qualifier is the drive or provider that is qualifing
/// the MSH path.
/// </value>
///
[Parameter(Position=1, ValueFromPipelineByPropertyName = true, ParameterSetName=qualifierSet, Mandatory=false)]
public SwitchParameter Qualifier
{
get
{
return qualifier;
} // get
set
{
qualifier = value;
} //set
} // Qualifier
/// <summary>
/// Determines if the qualifier should be returned
/// </summary>
///
/// <value>
/// If true the qualifier of the path will be returned.
/// The qualifier is the drive or provider that is qualifing
/// the MSH path.
/// </value>
///
[Parameter(ParameterSetName= noQualifierSet, Mandatory=false, ValueFromPipelineByPropertyName = true)]
public SwitchParameter NoQualifier
{
get
{
return noqualifier;
} // get
set
{
noqualifier = value;
} //set
} // NoQualifier
/// <summary>
/// Determines if the parent path should be returned
/// </summary>
///
/// <value>
/// If true the parent of the path will be returned.
/// </value>
///
[Parameter(ParameterSetName=parentSet, Mandatory=false, ValueFromPipelineByPropertyName = true)]
public SwitchParameter Parent
{
get
{
return parent;
} // get
set
{
parent = value;
} //set
} // Parent
/// <summary>
/// Determines if the leaf name should be returned
/// </summary>
///
/// <value>
/// If true the leaf name of the path will be returned.
/// </value>
///
[Parameter(ParameterSetName=leafSet, Mandatory=false, ValueFromPipelineByPropertyName = true)]
public SwitchParameter Leaf
{
get
{
return leaf;
} // get
set
{
leaf = value;
} //set
} // Leaf
/// <summary>
/// Determines if the path should be resolved before being parsed.
/// </summary>
/// <value></value>
[Parameter]
public SwitchParameter Resolve
{
get
{
return resolve;
} // get
set
{
resolve = value;
} //set
} // Resolve
/// <summary>
/// Determines if the path is an absolute path.
/// </summary>
///
[Parameter(ParameterSetName = isAbsoluteSet)]
public SwitchParameter IsAbsolute
{
get
{
return isAbsolute;
} // get
set
{
isAbsolute = value;
} //set
}
#endregion Parameters
#region parameter data
/// <summary>
/// The path to resolve
/// </summary>
private string[] paths;
/// <summary>
/// Determines if the qualifier of the path should be returned.
/// The qualifier is either the drive name or provider name that
/// is qualifying the path.
/// </summary>
private bool qualifier;
/// <summary>
/// Determines if the qualifier of the path should be returned.
/// If false, the qualifier will be returned. If true, it will
/// be stripped from the path.
/// The qualifier is either the drive name or provider name that
/// is qualifying the path.
/// </summary>
private bool noqualifier;
/// <summary>
/// Determines if the parent path of the specified path should be returned.
/// </summary>
private bool parent = true;
/// <summary>
/// Determines if the leaf name of the specified path should be returned.
/// </summary>
private bool leaf;
/// <summary>
/// Determines if the path(s) should be resolved before being parsed.
/// </summary>
private bool resolve;
/// <summary>
/// Determines if the path(s) are absolute paths.
/// </summary>
private bool isAbsolute;
#endregion parameter data
#region Command code
/// <summary>
/// Parses the specified path and returns the portion determined by the
/// boolean parameters.
/// </summary>
protected override void ProcessRecord ()
{
StringCollection pathsToParse = new StringCollection();
if (resolve)
{
CmdletProviderContext currentContext = CmdletProviderContext;
foreach (string path in paths)
{
// resolve the paths and then parse each one.
Collection<PathInfo> resolvedPaths = null;
try
{
resolvedPaths =
SessionState.Path.GetResolvedPSPathFromPSPath(path, currentContext);
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
continue;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
continue;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
continue;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
continue;
}
foreach (PathInfo resolvedPath in resolvedPaths)
{
try
{
if (InvokeProvider.Item.Exists(resolvedPath.Path, currentContext))
{
pathsToParse.Add(resolvedPath.Path);
}
}
catch (PSNotSupportedException notSupported)
{
WriteError(
new ErrorRecord(
notSupported.ErrorRecord,
notSupported));
continue;
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
continue;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
continue;
}
catch (ItemNotFoundException pathNotFound)
{
WriteError(
new ErrorRecord(
pathNotFound.ErrorRecord,
pathNotFound));
continue;
}
}
}
}
else
{
pathsToParse.AddRange(Path);
}
// Now parse each path
for (int index = 0; index < pathsToParse.Count; ++index)
{
string result = null;
switch (ParameterSetName)
{
case isAbsoluteSet:
string ignored = null;
bool isPathAbsolute =
SessionState.Path.IsPSAbsolute(pathsToParse[index], out ignored);
WriteObject(isPathAbsolute);
continue;
case qualifierSet :
int separatorIndex = pathsToParse[index].IndexOf(":", StringComparison.CurrentCulture);
if (separatorIndex < 0)
{
FormatException e =
new FormatException (
StringUtil.Format(NavigationResources.ParsePathFormatError, pathsToParse[index]));
WriteError (
new ErrorRecord (
e,
"ParsePathFormatError", // RENAME
ErrorCategory.InvalidArgument,
pathsToParse[index]));
continue;
}
else
{
// Check to see if it is provider or drive qualified
if (SessionState.Path.IsProviderQualified(pathsToParse[index]))
{
// The plus 2 is for the length of the provider separator
// which is "::"
result =
pathsToParse[index].Substring(
0,
separatorIndex + 2);
}
else
{
result =
pathsToParse[index].Substring(
0,
separatorIndex + 1);
}
}
break;
case parentSet :
case literalPathSet :
bool pathStartsWithRoot =
pathsToParse[index].StartsWith("\\", StringComparison.CurrentCulture) ||
pathsToParse[index].StartsWith("/", StringComparison.CurrentCulture);
try
{
result =
SessionState.Path.ParseParent(
pathsToParse[index],
String.Empty,
CmdletProviderContext,
true);
}
catch (PSNotSupportedException)
{
// Since getting the parent path is not supported,
// the provider must be a container, item, or drive
// provider. Since the paths for these types of
// providers can't be split, asking for the parent
// is asking for an empty string.
result = String.Empty;
}
break;
case leafSet :
try
{
result =
SessionState.Path.ParseChildName(
pathsToParse[index],
CmdletProviderContext,
true);
}
catch (PSNotSupportedException)
{
// Since getting the leaf part of a path is not supported,
// the provider must be a container, item, or drive
// provider. Since the paths for these types of
// providers can't be split, asking for the leaf
// is asking for the specified path back.
result = pathsToParse[index];
}
catch (DriveNotFoundException driveNotFound)
{
WriteError(
new ErrorRecord(
driveNotFound.ErrorRecord,
driveNotFound));
continue;
}
catch (ProviderNotFoundException providerNotFound)
{
WriteError(
new ErrorRecord(
providerNotFound.ErrorRecord,
providerNotFound));
continue;
}
break;
case noQualifierSet :
result = RemoveQualifier(pathsToParse[index]);
break;
default:
Dbg.Diagnostics.Assert(
false,
"Only a known parameter set should be called");
break;
} // switch
if (result != null)
{
WriteObject(result);
}
} // for each path
} // ProcessRecord
#endregion Command code
/// <summary>
/// Removes either the drive or provider qualifier or both from the path.
/// </summary>
///
/// <param name="path">
/// The path to strip the provider qualifier from.
/// </param>
///
/// <returns>
/// The path without the qualifier.
/// </returns>
///
private string RemoveQualifier(string path)
{
Dbg.Diagnostics.Assert(
path != null,
"Path should be verified by the caller");
string result = path;
if (SessionState.Path.IsProviderQualified(path))
{
int index = path.IndexOf("::", StringComparison.CurrentCulture);
if (index != -1)
{
// remove the qualifier
result = path.Substring(index + 2);
}
}
else
{
string driveName = String.Empty;
if (SessionState.Path.IsPSAbsolute(path, out driveName))
{
// Remove the drive name and colon
result = path.Substring(driveName.Length + 1);
}
}
return result;
} // RemoveQualifier
} // SplitPathCommand
} // namespace Microsoft.PowerShell.Commands