|
24 | 24 | import java.io.FileNotFoundException;
|
25 | 25 | import java.io.FileOutputStream;
|
26 | 26 | import java.io.IOException;
|
| 27 | +import java.nio.file.DirectoryNotEmptyException; |
| 28 | +import java.nio.file.Files; |
| 29 | +import java.nio.file.Path; |
27 | 30 |
|
28 | 31 | import javax.xml.parsers.ParserConfigurationException;
|
29 | 32 | import javax.xml.transform.TransformerException;
|
30 | 33 |
|
31 | 34 | import org.apache.commons.lang3.StringUtils;
|
| 35 | +import org.apache.commons.lang3.exception.ExceptionUtils; |
32 | 36 | import org.slf4j.Logger;
|
33 | 37 | import org.slf4j.LoggerFactory;
|
34 | 38 | import org.xwiki.component.manager.ComponentLookupException;
|
@@ -101,7 +105,7 @@ public File getRootFolder()
|
101 | 105 |
|
102 | 106 | /**
|
103 | 107 | * Load extension from repository storage.
|
104 |
| - * |
| 108 | + * |
105 | 109 | * @throws IOException when failing to load extensions
|
106 | 110 | */
|
107 | 111 | protected void loadExtensions() throws IOException
|
@@ -296,15 +300,63 @@ public void removeExtension(DefaultLocalExtension extension) throws IOException
|
296 | 300 | File descriptorFile = extension.getDescriptorFile();
|
297 | 301 |
|
298 | 302 | if (descriptorFile == null) {
|
299 |
| - throw new IOException("Exception does not exist"); |
| 303 | + throw new IOException( |
| 304 | + String.format("Extension [%s] does not exist: descriptor file is null", extension.getId().getId())); |
300 | 305 | }
|
301 | 306 |
|
302 |
| - descriptorFile.delete(); |
| 307 | + // Get extension file descriptor path |
| 308 | + Path extensionDescriptorFilePath = descriptorFile.toPath(); |
| 309 | + |
| 310 | + // Delete the extension descriptor file |
| 311 | + try { |
| 312 | + Files.delete(extensionDescriptorFilePath); |
| 313 | + } catch (FileNotFoundException e) { |
| 314 | + LOGGER.warn( |
| 315 | + "Couldn't delete the extension descriptor file [{}] when removing extension [{}], " |
| 316 | + + "because it doesn't exist. Root error: [{}]", |
| 317 | + descriptorFile.getAbsolutePath(), extension.getId().getId(), ExceptionUtils.getRootCauseMessage(e)); |
| 318 | + } |
303 | 319 |
|
304 | 320 | DefaultLocalExtensionFile extensionFile = extension.getFile();
|
305 | 321 |
|
306 | 322 | if (extensionFile != null) {
|
307 |
| - extensionFile.getFile().delete(); |
| 323 | + // Delete the extension file |
| 324 | + try { |
| 325 | + Files.delete(extensionFile.getFile().toPath()); |
| 326 | + } catch (FileNotFoundException e) { |
| 327 | + LOGGER.warn("Extension file [{}] was not found while removing [{}] extension", |
| 328 | + extensionFile.getAbsolutePath(), extension.getId().getId()); |
| 329 | + } |
| 330 | + } |
| 331 | + |
| 332 | + // Get the path to the folder that store the version of the extension being removed |
| 333 | + Path extensionVersionFolderPath = extensionDescriptorFilePath.getParent(); |
| 334 | + try { |
| 335 | + // Delete the extension version folder |
| 336 | + Files.delete(extensionDescriptorFilePath); |
| 337 | + |
| 338 | + // Try to delete the extension folder |
| 339 | + deleteExtensionFolderIfEmpty(extensionVersionFolderPath.getParent()); |
| 340 | + } catch (DirectoryNotEmptyException e) { |
| 341 | + LOGGER.warn("Extension version folder [{}] was not empty after removing the extension [{}]. Keeping it.", |
| 342 | + extensionDescriptorFilePath, extension.getId().getId()); |
| 343 | + } |
| 344 | + } |
| 345 | + |
| 346 | + /** |
| 347 | + * Try to delete the extension folder if empty (i.e. all versions have been removed) |
| 348 | + * |
| 349 | + * @param extensionFolderPath the path to the folder to delete |
| 350 | + * @throws IOException error (other than empty) when deleting the extension folder |
| 351 | + */ |
| 352 | + private static void deleteExtensionFolderIfEmpty(Path extensionFolderPath) throws IOException |
| 353 | + { |
| 354 | + try { |
| 355 | + Files.delete(extensionFolderPath); |
| 356 | + } catch (DirectoryNotEmptyException e) { |
| 357 | + // Folder not being empty is a valid scenario if some version of the extension are still installed |
| 358 | + LOGGER.debug("Extension folder [{}] was not empty after removing the extension. Keeping it.", |
| 359 | + extensionFolderPath); |
308 | 360 | }
|
309 | 361 |
|
310 | 362 | // Delete extension version folder if empty
|
|
0 commit comments