OLD | NEW |
1 # -*- coding: utf-8 -*- | 1 # -*- coding: utf-8 -*- |
2 """The path specification resolver.""" | 2 """The path specification resolver.""" |
3 | 3 |
4 from __future__ import unicode_literals | 4 from __future__ import unicode_literals |
5 | 5 |
6 from dfvfs.credentials import keychain | 6 from dfvfs.credentials import keychain |
7 from dfvfs.lib import definitions | 7 from dfvfs.lib import definitions |
8 from dfvfs.lib import errors | 8 from dfvfs.lib import errors |
9 from dfvfs.mount import manager as mount_manager | 9 from dfvfs.mount import manager as mount_manager |
10 from dfvfs.path import path_spec | 10 from dfvfs.path import path_spec |
11 from dfvfs.resolver import context | 11 from dfvfs.resolver import context |
12 | 12 |
13 | 13 |
14 class Resolver(object): | 14 class Resolver(object): |
15 """Path specification resolver.""" | 15 """Path specification resolver.""" |
16 | 16 |
17 _resolver_context = context.Context() | 17 _resolver_context = context.Context() |
18 _resolver_helpers = {} | 18 _resolver_helpers_manager = None |
19 | 19 |
20 key_chain = keychain.KeyChain() | 20 key_chain = keychain.KeyChain() |
21 | 21 |
22 @classmethod | 22 @classmethod |
23 def DeregisterHelper(cls, resolver_helper): | 23 def _GetResolverHelper(cls, type_indicator): |
24 """Deregisters a path specification resolver helper. | 24 """Retrieves the path specification resolver helper for the specified type. |
25 | 25 |
26 Args: | 26 Args: |
27 resolver_helper (ResolverHelper): resolver helper. | 27 type_indicator (str): type indicator. |
28 | 28 |
29 Raises: | 29 Returns: |
30 KeyError: if resolver helper object is not set for the corresponding | 30 ResolverHelper: a resolver helper. |
31 type indicator. | |
32 """ | 31 """ |
33 if resolver_helper.type_indicator not in cls._resolver_helpers: | 32 if not cls._resolver_helpers_manager: |
34 raise KeyError( | 33 # Delay the import of the resolver helpers manager to prevent circular |
35 'Resolver helper object not set for type indicator: {0:s}.'.format( | 34 # imports. |
36 resolver_helper.type_indicator)) | 35 from dfvfs.resolver_helpers import manager |
37 | 36 |
38 del cls._resolver_helpers[resolver_helper.type_indicator] | 37 cls._resolver_helpers_manager = manager.ResolverHelperManager |
| 38 |
| 39 return cls._resolver_helpers_manager.GetHelper(type_indicator) |
39 | 40 |
40 @classmethod | 41 @classmethod |
41 def OpenFileEntry(cls, path_spec_object, resolver_context=None): | 42 def OpenFileEntry(cls, path_spec_object, resolver_context=None): |
42 """Opens a file entry object defined by path specification. | 43 """Opens a file entry object defined by path specification. |
43 | 44 |
44 Args: | 45 Args: |
45 path_spec_object (PathSpec): path specification. | 46 path_spec_object (PathSpec): path specification. |
46 resolver_context (Optional[Context]): resolver context, where None | 47 resolver_context (Optional[Context]): resolver context, where None |
47 represents the built in context which is not multi process safe. | 48 represents the built in context which is not multi process safe. |
48 | 49 |
(...skipping 22 matching lines...) Expand all Loading... |
71 Args: | 72 Args: |
72 path_spec_object (PathSpec): path specification. | 73 path_spec_object (PathSpec): path specification. |
73 resolver_context (Optional[Context]): resolver context, where None | 74 resolver_context (Optional[Context]): resolver context, where None |
74 represents the built in context which is not multi process safe. | 75 represents the built in context which is not multi process safe. |
75 | 76 |
76 Returns: | 77 Returns: |
77 FileIO: file-like object or None if the path specification could not | 78 FileIO: file-like object or None if the path specification could not |
78 be resolved. | 79 be resolved. |
79 | 80 |
80 Raises: | 81 Raises: |
81 KeyError: if resolver helper object is not set for the corresponding | |
82 type indicator. | |
83 PathSpecError: if the path specification is incorrect. | 82 PathSpecError: if the path specification is incorrect. |
84 TypeError: if the path specification type is unsupported. | 83 TypeError: if the path specification type is unsupported. |
85 """ | 84 """ |
86 if not isinstance(path_spec_object, path_spec.PathSpec): | 85 if not isinstance(path_spec_object, path_spec.PathSpec): |
87 raise TypeError('Unsupported path specification type.') | 86 raise TypeError('Unsupported path specification type.') |
88 | 87 |
89 if resolver_context is None: | 88 if resolver_context is None: |
90 resolver_context = cls._resolver_context | 89 resolver_context = cls._resolver_context |
91 | 90 |
92 if path_spec_object.type_indicator == definitions.TYPE_INDICATOR_MOUNT: | 91 if path_spec_object.type_indicator == definitions.TYPE_INDICATOR_MOUNT: |
93 if path_spec_object.HasParent(): | 92 if path_spec_object.HasParent(): |
94 raise errors.PathSpecError( | 93 raise errors.PathSpecError( |
95 'Unsupported mount path specification with parent.') | 94 'Unsupported mount path specification with parent.') |
96 | 95 |
97 mount_point = getattr(path_spec_object, 'identifier', None) | 96 mount_point = getattr(path_spec_object, 'identifier', None) |
98 if not mount_point: | 97 if not mount_point: |
99 raise errors.PathSpecError( | 98 raise errors.PathSpecError( |
100 'Unsupported path specification without mount point identifier.') | 99 'Unsupported path specification without mount point identifier.') |
101 | 100 |
102 path_spec_object = mount_manager.MountPointManager.GetMountPoint( | 101 path_spec_object = mount_manager.MountPointManager.GetMountPoint( |
103 mount_point) | 102 mount_point) |
104 if not path_spec_object: | 103 if not path_spec_object: |
105 raise errors.MountPointError( | 104 raise errors.MountPointError( |
106 'No such mount point: {0:s}'.format(mount_point)) | 105 'No such mount point: {0:s}'.format(mount_point)) |
107 | 106 |
108 file_object = resolver_context.GetFileObject(path_spec_object) | 107 file_object = resolver_context.GetFileObject(path_spec_object) |
109 if not file_object: | 108 if not file_object: |
110 if path_spec_object.type_indicator not in cls._resolver_helpers: | 109 resolver_helper = cls._GetResolverHelper(path_spec_object.type_indicator) |
111 raise KeyError(( | |
112 'Resolver helper object not set for type indicator: ' | |
113 '{0:s}.').format(path_spec_object.type_indicator)) | |
114 | |
115 resolver_helper = cls._resolver_helpers[path_spec_object.type_indicator] | |
116 file_object = resolver_helper.NewFileObject(resolver_context) | 110 file_object = resolver_helper.NewFileObject(resolver_context) |
117 | 111 |
118 file_object.open(path_spec=path_spec_object) | 112 file_object.open(path_spec=path_spec_object) |
119 return file_object | 113 return file_object |
120 | 114 |
121 @classmethod | 115 @classmethod |
122 def OpenFileSystem(cls, path_spec_object, resolver_context=None): | 116 def OpenFileSystem(cls, path_spec_object, resolver_context=None): |
123 """Opens a file system object defined by path specification. | 117 """Opens a file system object defined by path specification. |
124 | 118 |
125 Args: | 119 Args: |
126 path_spec_object (PathSpec): path specification. | 120 path_spec_object (PathSpec): path specification. |
127 resolver_context (Optional[Context]): resolver context, where None | 121 resolver_context (Optional[Context]): resolver context, where None |
128 represents the built in context which is not multi process safe. | 122 represents the built in context which is not multi process safe. |
129 | 123 |
130 Returns: | 124 Returns: |
131 FileSystem: file system or None if the path specification could not | 125 FileSystem: file system or None if the path specification could not |
132 be resolved or has no file system object. | 126 be resolved or has no file system object. |
133 | 127 |
134 Raises: | 128 Raises: |
135 AccessError: if the access to open the file system was denied. | 129 AccessError: if the access to open the file system was denied. |
136 BackEndError: if the file system cannot be opened. | 130 BackEndError: if the file system cannot be opened. |
137 KeyError: if resolver helper object is not set for the corresponding | |
138 type indicator. | |
139 PathSpecError: if the path specification is incorrect. | 131 PathSpecError: if the path specification is incorrect. |
140 TypeError: if the path specification type is unsupported. | 132 TypeError: if the path specification type is unsupported. |
141 """ | 133 """ |
142 if not isinstance(path_spec_object, path_spec.PathSpec): | 134 if not isinstance(path_spec_object, path_spec.PathSpec): |
143 raise TypeError('Unsupported path specification type.') | 135 raise TypeError('Unsupported path specification type.') |
144 | 136 |
145 if resolver_context is None: | 137 if resolver_context is None: |
146 resolver_context = cls._resolver_context | 138 resolver_context = cls._resolver_context |
147 | 139 |
148 if path_spec_object.type_indicator == definitions.TYPE_INDICATOR_MOUNT: | 140 if path_spec_object.type_indicator == definitions.TYPE_INDICATOR_MOUNT: |
149 if path_spec_object.HasParent(): | 141 if path_spec_object.HasParent(): |
150 raise errors.PathSpecError( | 142 raise errors.PathSpecError( |
151 'Unsupported mount path specification with parent.') | 143 'Unsupported mount path specification with parent.') |
152 | 144 |
153 mount_point = getattr(path_spec_object, 'identifier', None) | 145 mount_point = getattr(path_spec_object, 'identifier', None) |
154 if not mount_point: | 146 if not mount_point: |
155 raise errors.PathSpecError( | 147 raise errors.PathSpecError( |
156 'Unsupported path specification without mount point identifier.') | 148 'Unsupported path specification without mount point identifier.') |
157 | 149 |
158 path_spec_object = mount_manager.MountPointManager.GetMountPoint( | 150 path_spec_object = mount_manager.MountPointManager.GetMountPoint( |
159 mount_point) | 151 mount_point) |
160 if not path_spec_object: | 152 if not path_spec_object: |
161 raise errors.MountPointError( | 153 raise errors.MountPointError( |
162 'No such mount point: {0:s}'.format(mount_point)) | 154 'No such mount point: {0:s}'.format(mount_point)) |
163 | 155 |
164 file_system = resolver_context.GetFileSystem(path_spec_object) | 156 file_system = resolver_context.GetFileSystem(path_spec_object) |
165 if not file_system: | 157 if not file_system: |
166 if path_spec_object.type_indicator not in cls._resolver_helpers: | 158 resolver_helper = cls._GetResolverHelper(path_spec_object.type_indicator) |
167 raise KeyError(( | |
168 'Resolver helper object not set for type indicator: ' | |
169 '{0:s}.').format(path_spec_object.type_indicator)) | |
170 | |
171 resolver_helper = cls._resolver_helpers[path_spec_object.type_indicator] | |
172 file_system = resolver_helper.NewFileSystem(resolver_context) | 159 file_system = resolver_helper.NewFileSystem(resolver_context) |
173 | 160 |
174 try: | 161 try: |
175 file_system.Open(path_spec_object) | 162 file_system.Open(path_spec_object) |
176 except (errors.AccessError, errors.PathSpecError): | 163 except (errors.AccessError, errors.PathSpecError): |
177 raise | 164 raise |
178 except (IOError, ValueError) as exception: | 165 except (IOError, ValueError) as exception: |
179 raise errors.BackEndError( | 166 raise errors.BackEndError( |
180 'Unable to open file system with error: {0:s}'.format(exception)) | 167 'Unable to open file system with error: {0:s}'.format(exception)) |
181 | 168 |
182 return file_system | 169 return file_system |
183 | |
184 @classmethod | |
185 def RegisterHelper(cls, resolver_helper): | |
186 """Registers a path specification resolver helper. | |
187 | |
188 Args: | |
189 resolver_helper (ResolverHelper): resolver helper. | |
190 | |
191 Raises: | |
192 KeyError: if resolver helper object is already set for the corresponding | |
193 type indicator. | |
194 """ | |
195 if resolver_helper.type_indicator in cls._resolver_helpers: | |
196 raise KeyError(( | |
197 'Resolver helper object already set for type indicator: ' | |
198 '{0!s}.').format(resolver_helper.type_indicator)) | |
199 | |
200 cls._resolver_helpers[resolver_helper.type_indicator] = resolver_helper | |
OLD | NEW |