-
-
Notifications
You must be signed in to change notification settings - Fork 182
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5093 from line-o/backport/5028
[6.x.x] Handle IllegalStateException in file:directory-list#2
- Loading branch information
Showing
3 changed files
with
147 additions
and
89 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,6 @@ | |
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.nio.file.Paths; | ||
import java.util.Date; | ||
|
||
import org.apache.logging.log4j.LogManager; | ||
|
@@ -34,11 +33,7 @@ | |
import org.exist.dom.QName; | ||
import org.exist.dom.memtree.MemTreeBuilder; | ||
import org.exist.util.FileUtils; | ||
import org.exist.xquery.BasicFunction; | ||
import org.exist.xquery.Cardinality; | ||
import org.exist.xquery.FunctionSignature; | ||
import org.exist.xquery.XPathException; | ||
import org.exist.xquery.XQueryContext; | ||
import org.exist.xquery.*; | ||
import org.exist.xquery.value.DateTimeValue; | ||
import org.exist.xquery.value.FunctionParameterSequenceType; | ||
import org.exist.xquery.value.FunctionReturnSequenceType; | ||
|
@@ -47,50 +42,56 @@ | |
import org.exist.xquery.value.SequenceType; | ||
import org.exist.xquery.value.Type; | ||
|
||
import static org.exist.xquery.modules.file.FileErrorCode.DIRECTORY_NOT_FOUND; | ||
|
||
/** | ||
* eXist File Module Extension DirectoryList | ||
* | ||
* <p> | ||
* Enumerate a list of files, including their size and modification time, found | ||
* in a specified directory, using a pattern | ||
* | ||
* @author <a href="mailto:[email protected]">Andrzej Taramina</a> | ||
* @author ljo | ||
* @serial 2009-08-09 | ||
* @version 1.2 | ||
* | ||
* @see | ||
* org.exist.xquery.BasicFunction#BasicFunction(org.exist.xquery.XQueryContext, | ||
* @serial 2009-08-09 | ||
* @see org.exist.xquery.BasicFunction#BasicFunction(org.exist.xquery.XQueryContext, | ||
* org.exist.xquery.FunctionSignature) | ||
*/ | ||
public class DirectoryList extends BasicFunction { | ||
|
||
private final static Logger logger = LogManager.getLogger(DirectoryList.class); | ||
|
||
final static String NAMESPACE_URI = FileModule.NAMESPACE_URI; | ||
final static String PREFIX = FileModule.PREFIX; | ||
|
||
public final static FunctionSignature[] signatures | ||
= { | ||
new FunctionSignature( | ||
new QName("directory-list", NAMESPACE_URI, PREFIX), | ||
"List all files, including their file size and modification time, " | ||
+ "found in or below a directory, $directory. Files are located in the server's " | ||
+ "file system, using filename patterns, $pattern. File pattern matching is based " | ||
+ "on code from Apache's Ant, thus following the same conventions. For example:\n\n" | ||
+ "'*.xml' matches any file ending with .xml in the current directory,\n- '**/*.xml' matches files " | ||
+ "in any directory below the specified directory. This method is only available to the DBA role.", | ||
new SequenceType[]{ | ||
static final String NAMESPACE_URI = FileModule.NAMESPACE_URI; | ||
static final String PREFIX = FileModule.PREFIX; | ||
public static final FunctionSignature[] signatures = { | ||
new FunctionSignature( | ||
new QName("directory-list", NAMESPACE_URI, PREFIX), | ||
"List all files, including their file size and modification time, " | ||
+ "found in or below a directory, $directory. Files are located in the server's " | ||
+ "file system, using filename patterns, $pattern. File pattern matching is based " | ||
+ "on code from Apache's Ant, thus following the same conventions. For example:\n\n" | ||
+ "'*.xml' matches any file ending with .xml in the current directory,\n- '**/*.xml' matches files " | ||
+ "in any directory below the specified directory. This method is only available to the DBA role.", | ||
new SequenceType[]{ | ||
new FunctionParameterSequenceType("path", Type.ITEM, | ||
Cardinality.EXACTLY_ONE, "The base directory path or URI in the file system where the files are located."), | ||
new FunctionParameterSequenceType("pattern", Type.STRING, | ||
Cardinality.ZERO_OR_MORE, "The file name pattern") | ||
}, | ||
new FunctionReturnSequenceType(Type.NODE, | ||
Cardinality.ZERO_OR_ONE, "a node fragment that shows all matching " | ||
+ "filenames, including their file size and modification time, and " | ||
+ "the subdirectory they were found in") | ||
) | ||
}; | ||
}, | ||
new FunctionReturnSequenceType(Type.NODE, | ||
Cardinality.ZERO_OR_ONE, "a node fragment that shows all matching " | ||
+ "filenames, including their file size and modification time, and " | ||
+ "the subdirectory they were found in") | ||
) | ||
}; | ||
static final QName FILE_ELEMENT = new QName("file", NAMESPACE_URI, PREFIX); | ||
static final QName LIST_ELEMENT = new QName("list", NAMESPACE_URI, PREFIX); | ||
|
||
static final QName DIRECTORY_ATTRIBUTE = new QName("directory", null, null); | ||
static final QName NAME_ATTRIBUTE = new QName("name", null, null); | ||
static final QName SIZE_ATTRIBUTE = new QName("size", null, null); | ||
static final QName HUMAN_SIZE_ATTRIBUTE = new QName("human-size", null, null); | ||
static final QName MODIFIED_ATTRIBUTE = new QName("modified", null, null); | ||
static final QName SUBDIR_ATTRIBUTE = new QName("subdir", null, null); | ||
private static final Logger logger = LogManager.getLogger(DirectoryList.class); | ||
|
||
public DirectoryList(final XQueryContext context, final FunctionSignature signature) { | ||
super(context, signature); | ||
|
@@ -117,11 +118,11 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro | |
final MemTreeBuilder builder = context.getDocumentBuilder(); | ||
|
||
builder.startDocument(); | ||
builder.startElement(new QName("list", NAMESPACE_URI, PREFIX), null); | ||
builder.addAttribute(new QName("directory", null, null), baseDir.toString()); | ||
builder.startElement(LIST_ELEMENT, null); | ||
builder.addAttribute(DIRECTORY_ATTRIBUTE, baseDir.toString()); | ||
try { | ||
final int patternsLen = patterns.getItemCount(); | ||
final String includes[] = new String[patternsLen]; | ||
final String[] includes = new String[patternsLen]; | ||
for (int i = 0; i < patternsLen; i++) { | ||
includes[i] = patterns.itemAt(0).getStringValue(); | ||
} | ||
|
@@ -139,76 +140,52 @@ public Sequence eval(final Sequence[] args, final Sequence contextSequence) thro | |
logger.debug("Found: {}", file.toAbsolutePath()); | ||
} | ||
|
||
String relPath = file.toString().substring(baseDir.toString().length() + 1); | ||
final String relPath = file.toString().substring(baseDir.toString().length() + 1); | ||
|
||
int lastSeparatorPosition = relPath.lastIndexOf(java.io.File.separatorChar); | ||
builder.startElement(FILE_ELEMENT, null); | ||
builder.addAttribute(NAME_ATTRIBUTE, FileUtils.fileName(file)); | ||
|
||
String relDir = null; | ||
if (lastSeparatorPosition >= 0) { | ||
relDir = relPath.substring(0, lastSeparatorPosition); | ||
relDir = relDir.replace(java.io.File.separatorChar, '/'); | ||
} | ||
|
||
builder.startElement(new QName("file", NAMESPACE_URI, PREFIX), null); | ||
|
||
builder.addAttribute(new QName("name", null, null), FileUtils.fileName(file)); | ||
final long sizeLong = FileUtils.sizeQuietly(file); | ||
builder.addAttribute(SIZE_ATTRIBUTE, Long.toString(sizeLong)); | ||
builder.addAttribute(HUMAN_SIZE_ATTRIBUTE, getHumanSize(sizeLong)); | ||
|
||
Long sizeLong = FileUtils.sizeQuietly(file); | ||
String sizeString = Long.toString(sizeLong); | ||
String humanSize = getHumanSize(sizeLong, sizeString); | ||
builder.addAttribute(MODIFIED_ATTRIBUTE, | ||
new DateTimeValue(this, | ||
new Date(Files.getLastModifiedTime(file).toMillis())).getStringValue()); | ||
|
||
builder.addAttribute(new QName("size", null, null), sizeString); | ||
builder.addAttribute(new QName("human-size", null, null), humanSize); | ||
builder.addAttribute(new QName("modified", null, null), new DateTimeValue(this, new Date(Files.getLastModifiedTime(file).toMillis())).getStringValue()); | ||
|
||
if (relDir != null && !relDir.isEmpty()) { | ||
builder.addAttribute(new QName("subdir", null, null), relDir); | ||
final int lastSeparatorPosition = relPath.lastIndexOf(java.io.File.separatorChar); | ||
if (lastSeparatorPosition >= 0) { | ||
final String relDir = relPath.substring(0, lastSeparatorPosition); | ||
if (!relDir.isEmpty()) { | ||
builder.addAttribute(SUBDIR_ATTRIBUTE, | ||
relDir.replace(java.io.File.separatorChar, '/')); | ||
} | ||
} | ||
|
||
builder.endElement(); | ||
|
||
} | ||
|
||
builder.endElement(); | ||
|
||
return (NodeValue) builder.getDocument().getDocumentElement(); | ||
} catch (final IOException e) { | ||
throw new XPathException(this, e.getMessage()); | ||
} catch (final IOException | IllegalStateException e) { | ||
throw new XPathException(this, DIRECTORY_NOT_FOUND, e.getMessage()); | ||
} finally { | ||
context.popDocumentContext(); | ||
} | ||
} | ||
|
||
private String getHumanSize(final Long sizeLong, final String sizeString) { | ||
String humanSize = "n/a"; | ||
int sizeDigits = sizeString.length(); | ||
|
||
if (sizeDigits < 4) { | ||
humanSize = Long.toString(Math.abs(sizeLong)); | ||
|
||
} else if (sizeDigits >= 4 && sizeDigits <= 6) { | ||
if (sizeLong < 1024) { | ||
// We don't want 0KB för e.g. 1006 Bytes. | ||
humanSize = Long.toString(Math.abs(sizeLong)); | ||
} else { | ||
humanSize = Math.abs(sizeLong / 1024) + "KB"; | ||
} | ||
|
||
} else if (sizeDigits >= 7 && sizeDigits <= 9) { | ||
if (sizeLong < 1048576) { | ||
humanSize = Math.abs(sizeLong / 1024) + "KB"; | ||
} else { | ||
humanSize = Math.abs(sizeLong / (1024 * 1024)) + "MB"; | ||
} | ||
|
||
} else if (sizeDigits > 9) { | ||
if (sizeLong < 1073741824) { | ||
humanSize = Math.abs((sizeLong / (1024 * 1024))) + "MB"; | ||
} else { | ||
humanSize = Math.abs((sizeLong / (1024 * 1024 * 1024))) + "GB"; | ||
} | ||
private String getHumanSize(final Long sizeLong) { | ||
if (sizeLong < 1024) { | ||
return Math.abs(sizeLong) + "B"; | ||
} | ||
if (sizeLong < 1048576) { | ||
return Math.abs(sizeLong / 1024) + "KB"; | ||
} | ||
if (sizeLong < 1073741824) { | ||
return Math.abs((sizeLong / (1024 * 1024))) + "MB"; | ||
} | ||
return humanSize; | ||
return Math.abs((sizeLong / (1024 * 1024 * 1024))) + "GB"; | ||
} | ||
|
||
} |
34 changes: 34 additions & 0 deletions
34
extensions/modules/file/src/main/java/org/exist/xquery/modules/file/FileErrorCode.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
/* | ||
* eXist-db Open Source Native XML Database | ||
* Copyright (C) 2001 The eXist-db Authors | ||
* | ||
* [email protected] | ||
* http://www.exist-db.org | ||
* | ||
* This library is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 2.1 of the License, or (at your option) any later version. | ||
* | ||
* This library is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public | ||
* License along with this library; if not, write to the Free Software | ||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
*/ | ||
package org.exist.xquery.modules.file; | ||
|
||
import org.exist.dom.QName; | ||
import org.exist.xquery.ErrorCodes; | ||
|
||
class FileErrorCode extends ErrorCodes.ErrorCode { | ||
public static final ErrorCodes.ErrorCode DIRECTORY_NOT_FOUND = new FileErrorCode("DIRECTORY_NOT_FOUND", | ||
"The directory could not be found."); | ||
|
||
FileErrorCode(final String code, final String description) { | ||
super(new QName(code, FileModule.NAMESPACE_URI, FileModule.PREFIX), description); | ||
} | ||
} |
47 changes: 47 additions & 0 deletions
47
extensions/modules/file/src/test/xquery/modules/file/directory-list.xqm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
(: | ||
: eXist-db Open Source Native XML Database | ||
: Copyright (C) 2001 The eXist-db Authors | ||
: | ||
: [email protected] | ||
: http://www.exist-db.org | ||
: | ||
: This library is free software; you can redistribute it and/or | ||
: modify it under the terms of the GNU Lesser General Public | ||
: License as published by the Free Software Foundation; either | ||
: version 2.1 of the License, or (at your option) any later version. | ||
: | ||
: This library is distributed in the hope that it will be useful, | ||
: but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
: Lesser General Public License for more details. | ||
: | ||
: You should have received a copy of the GNU Lesser General Public | ||
: License along with this library; if not, write to the Free Software | ||
: Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
:) | ||
xquery version "3.1"; | ||
|
||
module namespace dirlist="http://exist-db.org/testsuite/modules/file/dirlist"; | ||
|
||
|
||
import module namespace file="http://exist-db.org/xquery/file"; | ||
|
||
|
||
declare namespace test="http://exist-db.org/xquery/xqsuite"; | ||
|
||
|
||
declare | ||
%test:assertError("file:DIRECTORY_NOT_FOUND") | ||
function dirlist:non-existent-error-code() { | ||
file:directory-list("/non/existent", ()) | ||
}; | ||
|
||
declare | ||
%test:assertXPath("contains($result,'basedir /non/existent does not exist.') or contains($result,'basedir \non\existent does not exist.')") | ||
function dirlist:non-existent-error-description() { | ||
try { | ||
file:directory-list("/non/existent", ()) | ||
} catch file:DIRECTORY_NOT_FOUND { | ||
$err:description | ||
} | ||
}; |