#525 1.增加通配符匹配,对字符串可用通配符匹配,2.文件搜索可用AntPath,通配符,正则表达式匹配 3.FilePathUtils增加在windows下,将路径转为windows路径

This commit is contained in:
calvin1978
2017-01-23 13:22:36 +08:00
parent 11966020b6
commit 322280533e
13 changed files with 693 additions and 125 deletions
@@ -17,6 +17,8 @@ public abstract class Platforms {
// 文件路径分隔符
public static final String FILE_PATH_SEPARATOR = File.separator;
public static final char FILE_PATH_SEPARATOR_CHAR = File.separatorChar;
public static final char WINDOWS_FILE_PATH_SEPARATOR_CHAR='\\';
public static final char LINUX_FILE_PATH_SEPARATOR_CHAR='/';
// ClassPath分隔符
public static final String CLASS_PATH_SEPARATOR = File.pathSeparator;
@@ -71,7 +71,8 @@ public abstract class MapUtil {
*
* @see org.apache.commons.lang3.concurrent.ConcurrentUtils#putIfAbsent(ConcurrentMap, Object, Object)
*/
public static <K, V> V putIfAbsentWithFinalValue(final ConcurrentMap<K, V> map, final K key, final V value) {
public static <K, V> V putIfAbsentWithFinalValue(@NotNull final ConcurrentMap<K, V> map, final K key,
final V value) {
final V result = map.putIfAbsent(key, value);
return result != null ? result : value;
}
@@ -84,12 +85,8 @@ public abstract class MapUtil {
* @see org.apache.commons.lang3.concurrent.ConcurrentUtils#createIfAbsent(ConcurrentMap, Object,
* org.apache.commons.lang3.concurrent.ConcurrentInitializer)
*/
public static <K, V> V createIfAbsent(final ConcurrentMap<K, V> map, final K key,
final ValueCreator<? extends V> creator) {
if (map == null || creator == null) {
return null;
}
public static <K, V> V createIfAbsent(@NotNull final ConcurrentMap<K, V> map, final K key,
@NotNull final ValueCreator<? extends V> creator) {
final V value = map.get(key);
if (value == null) {
return putIfAbsentWithFinalValue(map, key, creator.get());
@@ -100,8 +97,6 @@ public abstract class MapUtil {
/**
* 创建Value值的回调函数
*
* from Common Lang
*
* @see MapUtil#createIfAbsent(ConcurrentMap, Object, ValueCreator)
*/
public interface ValueCreator<T> {
@@ -212,7 +207,7 @@ public abstract class MapUtil {
/**
* 相比HashMap,当key是枚举类时, 性能与空间占用俱佳.
*/
public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(Class<K> type) {
public static <K extends Enum<K>, V> EnumMap<K, V> newEnumMap(@NotNull Class<K> type) {
return new EnumMap<K, V>(Preconditions.checkNotNull(type));
}
@@ -1,49 +1,36 @@
package org.springside.modules.utils.io;
import java.io.File;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.StringUtils;
import org.springside.modules.utils.base.Platforms;
import org.springside.modules.utils.base.annotation.NotNull;
import org.springside.modules.utils.text.MoreStringUtil;
import com.google.common.io.Files;
/**
* 关于文件名,文件路径的工具集
* 关于文件路径的工具集
*
* @author calvin
*/
public abstract class FilePathUtil {
/**
* 获取文件名(不包含路径)
* 在Windows环境里,兼容Windows上的路径分割符,将 '/' 转回 '\'
*/
public static String getFileName(@NotNull String fullName) {
Validate.notEmpty(fullName);
int last = fullName.lastIndexOf(Platforms.FILE_PATH_SEPARATOR_CHAR);
return fullName.substring(last + 1);
}
public static String normalizePath(String path) {
if (Platforms.FILE_PATH_SEPARATOR_CHAR == Platforms.WINDOWS_FILE_PATH_SEPARATOR_CHAR
&& StringUtils.indexOf(path, Platforms.LINUX_FILE_PATH_SEPARATOR_CHAR) != -1) {
return StringUtils.replaceChars(path, Platforms.LINUX_FILE_PATH_SEPARATOR_CHAR,
Platforms.WINDOWS_FILE_PATH_SEPARATOR_CHAR);
}
return path;
/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(File file) {
return Files.getFileExtension(file.getName());
}
/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(String fullName) {
return Files.getFileExtension(fullName);
}
/**
* 将路径整理,如 "a/../b",整理成 "b"
*/
public static String simplifyPath(String pathName) {
return Files.simplifyPath(pathName);
public static String simplifyPath(String path) {
return Files.simplifyPath(path);
}
/**
@@ -76,4 +63,5 @@ public abstract class FilePathUtil {
public static String getJarPath(Class<?> clazz) {
return clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
}
}
@@ -0,0 +1,145 @@
package org.springside.modules.utils.io;
import java.io.File;
import java.util.List;
import java.util.regex.Pattern;
import org.springside.modules.utils.text.WildcardMatcher;
import com.google.common.base.Predicate;
import com.google.common.collect.TreeTraverser;
import com.google.common.io.Files;
public class FileTreeWalker {
/**
* 前序递归列出所有文件, 包含文件与目录,及根目录本身.
*
* 前序即先列出父目录,在列出子目录. 如要后序遍历, 直接使用Files.fileTreeTraverser()
*/
public static List<File> listAll(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).toList();
}
/**
* 前序递归列出所有文件, 只包含文件.
*/
public static List<File> listFile(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(Files.isFile()).toList();
}
/**
* 前序递归列出所有文件, 列出后缀名匹配的文件. (后缀名不包含.)
*/
public static List<File> listFileWithExtension(final File rootDir, final String extension) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new FileExtensionFilter(extension)).toList();
}
/**
* 前序递归列出所有文件, 列出文件名匹配通配符的文件
*
* 如 ("/a/b/hello.txt", "he*") 将被返回
*/
public static List<File> listFileWithWildcardFileName(final File rootDir, final String fileNamePattern) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new WildcardFileNameFilter(fileNamePattern))
.toList();
}
/**
* 前序递归列出所有文件, 列出文件名匹配正则表达式的文件
*
* 如 ("/a/b/hello.txt", "he.*\.text") 将被返回
*/
public static List<File> listFileWithRegexFileName(final File rootDir, final String regexFileNamePattern) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir)
.filter(new RegexFileNameFilter(regexFileNamePattern)).toList();
}
/**
* 前序递归列出所有文件, 列出符合ant path风格表达式的文件
*
* 如 ("/a/b/hello.txt", "he.*\.text") 将被返回
*/
public static List<File> listFileWithAntPath(final File rootDir, final String antPathPattern) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new AntPathFilter(antPathPattern)).toList();
}
/**
* 直接使用Guava的TreeTraverser,获得更大的灵活度, 比如加入各类filter,前序/后序的选择,一边遍历一边操作
*
* <pre>
* FileUtil.fileTreeTraverser().preOrderTraversal(root).iterator();
* </pre>
*/
public static TreeTraverser<File> fileTreeTraverser() {
return Files.fileTreeTraverser();
}
/**
* 以文件名正则表达式为filter,配合fileTreeTraverser使用
*/
public static final class RegexFileNameFilter implements Predicate<File> {
private final Pattern pattern;
private RegexFileNameFilter(String pattern) {
this.pattern = Pattern.compile(pattern);
}
@Override
public boolean apply(File input) {
return input.isFile() && pattern.matcher(input.getName()).matches();
}
}
/**
* 以文件名通配符为filter,配合fileTreeTraverser使用.
*
* @param pattern 支持*与?的通配符,如hello*.txt 匹配 helloworld.txt
*/
public static final class WildcardFileNameFilter implements Predicate<File> {
private final String pattern;
private WildcardFileNameFilter(String pattern) {
this.pattern = pattern;
}
@Override
public boolean apply(File input) {
return input.isFile() && WildcardMatcher.match(input.getName(), pattern);
}
}
/**
* 以文件名后缀做filter,配合fileTreeTraverser使用
*/
public static final class FileExtensionFilter implements Predicate<File> {
private final String extension;
private FileExtensionFilter(String extension) {
this.extension = extension;
}
@Override
public boolean apply(File input) {
return input.isFile() && extension.equals(FileUtil.getFileExtension(input));
}
}
/**
* 以ant风格的path为filter,配合fileTreeTraverser使用.
*
* @param pattern 支持ant风格的通配符,如/var/?/a?.txt 匹配 /var/b/ab.txt, 其他通配符包括**,*
*/
public static final class AntPathFilter implements Predicate<File> {
private final String pattern;
private AntPathFilter(String pattern) {
this.pattern = pattern;
}
@Override
public boolean apply(File input) {
return input.isFile() && WildcardMatcher.matchPath(input.getName(), pattern);
}
}
}
@@ -14,12 +14,11 @@ import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.springside.modules.utils.base.Platforms;
import org.springside.modules.utils.base.annotation.NotNull;
import org.springside.modules.utils.base.annotation.Nullable;
import org.springside.modules.utils.text.Charsets;
import com.google.common.base.Predicate;
import com.google.common.collect.TreeTraverser;
import com.google.common.io.Files;
/**
@@ -223,40 +222,6 @@ public abstract class FileUtil {
}
}
/**
* 前序递归列出所有文件, 包含文件与目录,及根目录本身.
*
* 前序即先列出父目录,在列出子目录. 如要后序遍历, 直接使用Files.fileTreeTraverser()
*/
public static List<File> listAll(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).toList();
}
/**
* 前序递归列出所有文件, 只包含文件.
*/
public static List<File> listFile(File rootDir) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(Files.isFile()).toList();
}
/**
* 前序递归列出所有文件, 只包含后缀名匹配的文件. (后缀名不包含.)
*/
public static List<File> listFileWithExtension(final File rootDir, final String extension) {
return Files.fileTreeTraverser().preOrderTraversal(rootDir).filter(new FileExtensionFilter(extension)).toList();
}
/**
* 直接使用Guava的TreeTraverser,获得更大的灵活度, 比如加入各类filter,前序/后序的选择,一边遍历一边操作
*
* <pre>
* FileUtil.fileTreeTraverser().preOrderTraversal(root).iterator();
* </pre>
*/
public static TreeTraverser<File> fileTreeTraverser() {
return Files.fileTreeTraverser();
}
/**
* 判断目录是否存在, from Jodd
*/
@@ -349,18 +314,26 @@ public abstract class FileUtil {
}
/**
* 以文件名后缀做filter,配合fileTreeTraverser使用
* 获取文件名(不包含路径)
*/
public static final class FileExtensionFilter implements Predicate<File> {
private final String extension;
private FileExtensionFilter(String extension) {
this.extension = extension;
}
@Override
public boolean apply(File input) {
return input.isFile() && extension.equals(FilePathUtil.getFileExtension(input));
}
public static String getFileName(@NotNull String fullName) {
Validate.notEmpty(fullName);
int last = fullName.lastIndexOf(Platforms.FILE_PATH_SEPARATOR_CHAR);
return fullName.substring(last + 1);
}
/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(File file) {
return Files.getFileExtension(file.getName());
}
/**
* 获取文件名的扩展名部分(不包含.)
*/
public static String getFileExtension(String fullName) {
return Files.getFileExtension(fullName);
}
}
@@ -28,9 +28,10 @@ import com.google.common.io.Resources;
*
* 所以resourceName无需以"/"打头即表示jar file中的根目录,带了"/" 反而导致JarFile.getEntry(resouceName)时没有返回.
*
* 指定contextClass时,class.getResource()会先对name进行处理再交给classLoader,打头的"/"的会被去除,不以"/"打头则表示与该contextClass package的相对路径, 会先转为绝对路径.
* 指定contextClass时,class.getResource()会先对name进行处理再交给classLoader,打头的"/"的会被去除,不以"/"打头则表示与该contextClass package的相对路径,
* 会先转为绝对路径.
*
* 3.同名资源
* 3.同名资源
*
* 如果有多个同名资源,除非调用getResources()获取全部资源,否则在URLClassLoader中按ClassPath顺序打开第一个命中的Jar文件.
*/
@@ -0,0 +1,268 @@
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package org.springside.modules.utils.text;
import org.apache.commons.lang3.StringUtils;
import org.springside.modules.utils.base.Platforms;
/**
* Checks whether a string or path matches a given wildcard pattern. Possible patterns allow to match single characters
* ('?') or any count of characters ('*'). Wildcard characters can be escaped (by an '\'). When matching path, deep tree
* wildcard also can be used ('**').
* <p>
* This method uses recursive matching, as in linux or windows. regexp works the same. This method is very fast,
* comparing to similar implementations.
*/
public class WildcardMatcher {
/**
* Checks whether a string matches a given wildcard pattern.
*
* @param string input string
* @param pattern pattern to match
* @return <code>true</code> if string matches the pattern, otherwise <code>false</code>
*/
public static boolean match(CharSequence string, CharSequence pattern) {
return match(string, pattern, 0, 0);
}
/**
* Internal matching recursive function.
*/
private static boolean match(CharSequence string, CharSequence pattern, int sNdx, int pNdx) {
int pLen = pattern.length();
if (pLen == 1) {
if (pattern.charAt(0) == '*') { // speed-up
return true;
}
}
int sLen = string.length();
boolean nextIsNotWildcard = false;
while (true) {
// check if end of string and/or pattern occurred
if ((sNdx >= sLen)) { // end of string still may have pending '*' in pattern
while ((pNdx < pLen) && (pattern.charAt(pNdx) == '*')) {
pNdx++;
}
return pNdx >= pLen;
}
if (pNdx >= pLen) { // end of pattern, but not end of the string
return false;
}
char p = pattern.charAt(pNdx); // pattern char
// perform logic
if (!nextIsNotWildcard) {
if (p == '\\') {
pNdx++;
nextIsNotWildcard = true;
continue;
}
if (p == '?') {
sNdx++;
pNdx++;
continue;
}
if (p == '*') {
char pNext = 0; // next pattern char
if (pNdx + 1 < pLen) {
pNext = pattern.charAt(pNdx + 1);
}
if (pNext == '*') { // double '*' have the same effect as one '*'
pNdx++;
continue;
}
int i;
pNdx++;
// find recursively if there is any substring from the end of the
// line that matches the rest of the pattern !!!
for (i = string.length(); i >= sNdx; i--) {
if (match(string, pattern, i, pNdx)) {
return true;
}
}
return false;
}
} else {
nextIsNotWildcard = false;
}
// check if pattern char and string char are equals
if (p != string.charAt(sNdx)) {
return false;
}
// everything matches for now, continue
sNdx++;
pNdx++;
}
}
// ---------------------------------------------------------------- utilities
/**
* Matches string to at least one pattern. Returns index of matched pattern, or <code>-1</code> otherwise.
* @see #match(CharSequence, CharSequence)
*/
public static int matchOne(String src, String[] patterns) {
for (int i = 0; i < patterns.length; i++) {
if (match(src, patterns[i])) {
return i;
}
}
return -1;
}
/**
* Matches path to at least one pattern. Returns index of matched pattern or <code>-1</code> otherwise.
* @see #matchPath(String, String)
*/
public static int matchPathOne(String path, String[] patterns) {
for (int i = 0; i < patterns.length; i++) {
if (matchPath(path, patterns[i])) {
return i;
}
}
return -1;
}
// ---------------------------------------------------------------- path
protected static final String PATH_MATCH = "**";
protected static final String PATH_SEPARATORS = "/\\";
/**
* Matches path against pattern using *, ? and ** wildcards. Both path and the pattern are tokenized on path
* separators (both \ and /). '**' represents deep tree wildcard, as in Ant.
*/
public static boolean matchPath(String path, String pattern) {
String[] pathElements = StringUtils.split(path, Platforms.FILE_PATH_SEPARATOR_CHAR);
String[] patternElements = StringUtils.split(pattern, Platforms.FILE_PATH_SEPARATOR_CHAR);
return matchTokens(pathElements, patternElements);
}
/**
* Match tokenized string and pattern.
*/
protected static boolean matchTokens(String[] tokens, String[] patterns) {
int patNdxStart = 0;
int patNdxEnd = patterns.length - 1;
int tokNdxStart = 0;
int tokNdxEnd = tokens.length - 1;
while ((patNdxStart <= patNdxEnd) && (tokNdxStart <= tokNdxEnd)) { // find first **
String patDir = patterns[patNdxStart];
if (patDir.equals(PATH_MATCH)) {
break;
}
if (!match(tokens[tokNdxStart], patDir)) {
return false;
}
patNdxStart++;
tokNdxStart++;
}
if (tokNdxStart > tokNdxEnd) {
for (int i = patNdxStart; i <= patNdxEnd; i++) { // string is finished
if (!patterns[i].equals(PATH_MATCH)) {
return false;
}
}
return true;
}
if (patNdxStart > patNdxEnd) {
return false; // string is not finished, but pattern is
}
while ((patNdxStart <= patNdxEnd) && (tokNdxStart <= tokNdxEnd)) { // to the last **
String patDir = patterns[patNdxEnd];
if (patDir.equals(PATH_MATCH)) {
break;
}
if (!match(tokens[tokNdxEnd], patDir)) {
return false;
}
patNdxEnd--;
tokNdxEnd--;
}
if (tokNdxStart > tokNdxEnd) {
for (int i = patNdxStart; i <= patNdxEnd; i++) { // string is finished
if (!patterns[i].equals(PATH_MATCH)) {
return false;
}
}
return true;
}
while ((patNdxStart != patNdxEnd) && (tokNdxStart <= tokNdxEnd)) {
int patIdxTmp = -1;
for (int i = patNdxStart + 1; i <= patNdxEnd; i++) {
if (patterns[i].equals(PATH_MATCH)) {
patIdxTmp = i;
break;
}
}
if (patIdxTmp == patNdxStart + 1) {
patNdxStart++; // skip **/** situation
continue;
}
// find the pattern between padIdxStart & padIdxTmp in str between strIdxStart & strIdxEnd
int patLength = (patIdxTmp - patNdxStart - 1);
int strLength = (tokNdxEnd - tokNdxStart + 1);
int ndx = -1;
strLoop: for (int i = 0; i <= strLength - patLength; i++) {
for (int j = 0; j < patLength; j++) {
String subPat = patterns[patNdxStart + j + 1];
String subStr = tokens[tokNdxStart + i + j];
if (!match(subStr, subPat)) {
continue strLoop;
}
}
ndx = tokNdxStart + i;
break;
}
if (ndx == -1) {
return false;
}
patNdxStart = patIdxTmp;
tokNdxStart = ndx + patLength;
}
for (int i = patNdxStart; i <= patNdxEnd; i++) {
if (!patterns[i].equals(PATH_MATCH)) {
return false;
}
}
return true;
}
}
@@ -108,10 +108,117 @@ public class MapUtilTest {
} catch (Throwable t) {
assertThat(t).isInstanceOf(UnsupportedOperationException.class);
}
}
@Test
public void weakMap() {
ConcurrentMap<MyBean, MyBean> weakKeyMap = MapUtil.createWeakKeyConcurrentHashMap(10, 1);
initExpireAllMap(weakKeyMap);
System.gc();
assertThat(weakKeyMap.get(new MyBean("A"))).isNull();
assertThat(weakKeyMap).hasSize(1); // key仍然在
ConcurrentMap<MyBean, MyBean> weakKeyMap2 = MapUtil.createWeakKeyConcurrentHashMap(10, 1);
MyBean value = new MyBean("B");
initExpireKeyMap(weakKeyMap2, value);
System.gc();
assertThat(weakKeyMap2.get(new MyBean("A"))).isNull();
ConcurrentMap<MyBean, MyBean> weakKeyMap3 = MapUtil.createWeakKeyConcurrentHashMap(10, 1);
MyBean key = new MyBean("A");
initExpireValueMap(weakKeyMap3, key);
System.gc();
assertThat(weakKeyMap3.get(key)).isEqualTo(new MyBean("B"));
// weak value
ConcurrentMap<MyBean, MyBean> weakValueMap = MapUtil.createWeakValueConcurrentHashMap(10, 1);
initExpireAllMap(weakValueMap);
System.gc();
assertThat(weakValueMap.get(new MyBean("A"))).isNull();
ConcurrentMap<MyBean, MyBean> weakValueMap2 = MapUtil.createWeakValueConcurrentHashMap(10, 1);
MyBean value2 = new MyBean("B");
initExpireKeyMap(weakValueMap2, value2);
System.gc();
assertThat(weakValueMap2.get(new MyBean("A"))).isEqualTo(new MyBean("B"));
ConcurrentMap<MyBean, MyBean> weakValueMap3 = MapUtil.createWeakValueConcurrentHashMap(10, 1);
MyBean key3 = new MyBean("A");
initExpireValueMap(weakValueMap3, key3);
System.gc();
assertThat(weakValueMap3.get(new MyBean("A"))).isNull();
}
// 抽出子函数,使得Key/Value的生命周琦过期
private void initExpireAllMap(ConcurrentMap<MyBean, MyBean> weakKeyMap) {
MyBean key = new MyBean("A");
MyBean value = new MyBean("B");
weakKeyMap.put(key, value);
assertThat(weakKeyMap.get(key)).isEqualTo(value);
}
// 抽出子函数,使得key过期,value不过期
private void initExpireKeyMap(ConcurrentMap<MyBean, MyBean> weakKeyMap, MyBean value) {
MyBean key = new MyBean("A");
weakKeyMap.put(key, value);
assertThat(weakKeyMap.get(key)).isEqualTo(value);
}
// 抽出子函数,使得key不过期,value过期
private void initExpireValueMap(ConcurrentMap<MyBean, MyBean> weakKeyMap, MyBean key) {
MyBean value = new MyBean("B");
weakKeyMap.put(key, value);
assertThat(weakKeyMap.get(key)).isEqualTo(value);
}
// 抽出子函数,使得Key/Value的生命周琦过期
private void initWeakValue(ConcurrentMap<MyBean, MyBean> weakKeyMap) {
MyBean key = new MyBean("A");
MyBean value = new MyBean("B");
weakKeyMap.put(key, value);
assertThat(weakKeyMap.get(new MyBean("A"))).isEqualTo(value);
}
public static class MyBean {
String name;
public MyBean(String name) {
this.name = name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MyBean other = (MyBean) obj;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public enum EnumA {
A, B, C
}
@Test
public void IntObjectHashMap(){
}
}
@@ -9,18 +9,7 @@ import com.google.common.io.Files;
public class FilePathUtilTest {
private String sep = Platforms.FILE_PATH_SEPARATOR;
@Test
public void getName() {
assertThat(FilePathUtil.getFileName(sep + "a" + sep + "d" + sep + "b" + sep + "abc.txt")).isEqualTo("abc.txt");
assertThat(FilePathUtil.getFileName("abc.txt")).isEqualTo("abc.txt");
assertThat(FilePathUtil.getFileExtension(sep + "a" + sep + "d" + sep + "b" + sep + "abc.txt")).isEqualTo("txt");
assertThat(FilePathUtil.getFileExtension(sep + "a" + sep + "d" + sep + "b" + sep + "abc")).isEqualTo("");
assertThat(FilePathUtil.getFileExtension(sep + "a" + sep + "d" + sep + "b" + sep + "abc.")).isEqualTo("");
}
char sep = Platforms.FILE_PATH_SEPARATOR_CHAR;
@Test
public void pathName() {
@@ -40,5 +29,4 @@ public class FilePathUtilTest {
System.out.println("the jar file contains Files.class" + FilePathUtil.getJarPath(Files.class));
assertThat(FilePathUtil.getJarPath(Files.class)).endsWith("guava-20.0.jar");
}
}
@@ -0,0 +1,60 @@
package org.springside.modules.utils.io;
import static org.assertj.core.api.Assertions.*;
import java.io.File;
import java.io.IOException;
import java.util.List;
import org.junit.Test;
import org.springside.modules.utils.number.RandomUtil;
public class FileTreeWalkerTest {
@Test
public void listFile() throws IOException {
File tmpDir = FileUtil.createTempDir();
List<File> all = FileTreeWalker.listAll(tmpDir);
assertThat(all).hasSize(1);
List<File> files = FileTreeWalker.listFile(tmpDir);
assertThat(files).hasSize(0);
FileUtil.touch(FilePathUtil.contact(tmpDir.getAbsolutePath(), "tmp-" + RandomUtil.nextInt()) + ".tmp");
FileUtil.touch(FilePathUtil.contact(tmpDir.getAbsolutePath(), "tmp-" + RandomUtil.nextInt()) + ".abc");
String childDir = FilePathUtil.contact(tmpDir.getAbsolutePath(), "tmp-" + RandomUtil.nextInt());
FileUtil.makeSureDirExists(childDir);
FileUtil.touch(FilePathUtil.contact(childDir, "tmp-" + RandomUtil.nextInt()) + ".tmp");
all = FileTreeWalker.listAll(tmpDir);
assertThat(all).hasSize(5);
files = FileTreeWalker.listFile(tmpDir);
assertThat(files).hasSize(3);
files = FileTreeWalker.listFileWithExtension(tmpDir, "tmp");
assertThat(files).hasSize(2);
files = FileTreeWalker.listFileWithExtension(tmpDir, "tp");
assertThat(files).hasSize(0);
files = FileTreeWalker.listFileWithWildcardFileName(tmpDir, "*.tmp");
assertThat(files).hasSize(2);
files = FileTreeWalker.listFileWithWildcardFileName(tmpDir, "*.tp");
assertThat(files).hasSize(0);
files = FileTreeWalker.listFileWithRegexFileName(tmpDir, ".*\\.tmp");
assertThat(files).hasSize(2);
files = FileTreeWalker.listFileWithRegexFileName(tmpDir, ".*\\.tp");
assertThat(files).hasSize(0);
FileUtil.deleteDir(tmpDir);
assertThat(FileUtil.isDirExists(tmpDir)).isFalse();
}
}
@@ -68,36 +68,17 @@ public class FileUtilTest {
}
}
private String sep = Platforms.FILE_PATH_SEPARATOR;
@Test
public void listFile() throws IOException {
File tmpDir = FileUtil.createTempDir();
public void getName() {
List<File> all = FileUtil.listAll(tmpDir);
assertThat(all).hasSize(1);
assertThat(FileUtil.getFileName(FilePathUtil.normalizePath("/a/d/b/abc.txt"))).isEqualTo("abc.txt");
assertThat(FileUtil.getFileName("abc.txt")).isEqualTo("abc.txt");
List<File> files = FileUtil.listFile(tmpDir);
assertThat(files).hasSize(0);
FileUtil.touch(FilePathUtil.contact(tmpDir.getAbsolutePath(), "tmp-" + RandomUtil.nextInt()) + ".tmp");
FileUtil.touch(FilePathUtil.contact(tmpDir.getAbsolutePath(), "tmp-" + RandomUtil.nextInt()) + ".abc");
String childDir = FilePathUtil.contact(tmpDir.getAbsolutePath(), "tmp-" + RandomUtil.nextInt());
FileUtil.makeSureDirExists(childDir);
FileUtil.touch(FilePathUtil.contact(childDir, "tmp-" + RandomUtil.nextInt()) + ".tmp");
all = FileUtil.listAll(tmpDir);
assertThat(all).hasSize(5);
files = FileUtil.listFile(tmpDir);
assertThat(files).hasSize(3);
files = FileUtil.listFileWithExtension(tmpDir, "tmp");
assertThat(files).hasSize(2);
FileUtil.deleteDir(tmpDir);
assertThat(FileUtil.isDirExists(tmpDir)).isFalse();
assertThat(FileUtil.getFileExtension(FilePathUtil.normalizePath("a/d/b/abc.txt"))).isEqualTo("txt");
assertThat(FileUtil.getFileExtension(FilePathUtil.normalizePath("/a/d/b/abc"))).isEqualTo("");
assertThat(FileUtil.getFileExtension(FilePathUtil.normalizePath("/a/d/b/abc."))).isEqualTo("");
}
@@ -22,10 +22,22 @@ public class FastMethodInvokerTest {
age = fastGetAge.invoke(student2);
assertThat(age).isEqualTo(30);
FastMethodInvoker fastGetAge2 = FastMethodInvoker.createGetter(Student.class, "age");
age = fastGetAge2.invoke(student1);
assertThat(age).isEqualTo(20);
age = fastGetAge2.invoke(student2);
assertThat(age).isEqualTo(30);
FastMethodInvoker fastSetAge = FastMethodInvoker.create(Student.class, "setAge", int.class);
fastSetAge.invoke(student1, 1);
assertThat(student1.getAge()).isEqualTo(1);
FastMethodInvoker fastSetAge2 = FastMethodInvoker.createSetter(Student.class, "age", int.class);
fastSetAge2.invoke(student1, 3);
assertThat(student1.getAge()).isEqualTo(3);
}
public static class Student {
@@ -0,0 +1,48 @@
package org.springside.modules.utils.text;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
public class WildcardMatcherTest {
@Test
public void matchString() {
assertThat(WildcardMatcher.match("abc", "*")).isTrue();
assertThat(WildcardMatcher.match("abc", "*c")).isTrue();
assertThat(WildcardMatcher.match("abc", "a*")).isTrue();
assertThat(WildcardMatcher.match("abc", "a*c")).isTrue();
assertThat(WildcardMatcher.match("abc", "a?c")).isTrue();
assertThat(WildcardMatcher.match("abcd", "a?c?")).isTrue();
assertThat(WildcardMatcher.match("abcd", "a??d")).isTrue();
assertThat(WildcardMatcher.match("abcde", "a*d?")).isTrue();
assertThat(WildcardMatcher.match("abcde", "a*d")).isFalse();
assertThat(WildcardMatcher.match("abcde", "a*x")).isFalse();
assertThat(WildcardMatcher.match("abcde", "a*df")).isFalse();
assertThat(WildcardMatcher.match("abcde", "?abcd")).isFalse();
assertThat(WildcardMatcher.match("ab\\\\*cde", "ab\\\\*c*")).isTrue();
assertThat(WildcardMatcher.match("ab\\\\*cde", "ab\\\\*?de")).isTrue();
}
@Test
public void matchPath() {
assertThat(WildcardMatcher.matchPath("/a/b/dd", "**")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/dd", "**/dd")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/c/dd", "/a/**/dd")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/dd", "/a/*/dd")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/dd", "/a/*/d?")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/ddxxa", "/a/*/dd*")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/ddxxa", "/a/?/dd*")).isTrue();
assertThat(WildcardMatcher.matchPath("a/b/ddxxa", "a/?/dd*")).isTrue();
assertThat(WildcardMatcher.matchPath("a/b/dd", "**/dd")).isTrue();
assertThat(WildcardMatcher.matchPath("/a/b/c/dd", "/a/*/dd")).isFalse();
}
}