diff --git a/.github/workflows/maven.yml b/.github/workflows/maven-build.yml similarity index 84% rename from .github/workflows/maven.yml rename to .github/workflows/maven-build.yml index 7a56ba6ac..c3457501c 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven-build.yml @@ -6,7 +6,7 @@ # separate terms of service, privacy policy, and support # documentation. -name: Java CI with Maven +name: Maven Build on: push: @@ -19,10 +19,11 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - java: [ '8' ] + java: [ '8', '11' , '17' , '21' ] steps: - - uses: actions/checkout@v4 - - name: Java ${{ matrix.Java }} + - name: Checkout Source + uses: actions/checkout@v4 + - name: Setup JDK ${{ matrix.Java }} uses: actions/setup-java@v4 with: distribution: 'temurin' diff --git a/.github/workflows/maven-publish.yml b/.github/workflows/maven-publish.yml new file mode 100644 index 000000000..f81bc8d19 --- /dev/null +++ b/.github/workflows/maven-publish.yml @@ -0,0 +1,45 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-maven + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Maven Publish + +on: + push: + branches: [ 'release' ] + workflow_dispatch: + inputs: + revision: + description: 'The version to release' + required: true + default: '0.0.1-SNAPSHOT' + +jobs: + build: + runs-on: ubuntu-latest + if: ${{ inputs.revision }} + steps: + - name: Checkout Source + uses: actions/checkout@v4 + + - name: Setup Maven Central Repository + uses: actions/setup-java@v4 + with: + java-version: '11' + distribution: 'temurin' + server-id: ossrh + server-username: MAVEN_USERNAME + server-password: MAVEN_PASSWORD + cache: maven + + - name: Publish package + run: mvn --batch-mode --update-snapshots -Drevision=${{ inputs.revision }} -Prelease clean deploy + env: + MAVEN_USERNAME: ${{ secrets.OSS_SONATYPE_USERNAME }} + MAVEN_PASSWORD: ${{ secrets.OSS_SONATYPE_PASSWORD }} + MAVEN_GPG_KEY: ${{ secrets.OSS_SIGNING_KEY }} + MAVEN_GPG_PASSPHRASE : ${{ secrets.OSS_SIGNING_PASSWORD }} \ No newline at end of file diff --git a/README.md b/README.md index cf67351e5..e6e9bb7e1 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # microsphere-framework -The common feautres used in the other microsphere sub-projects +The common features used in the other microsphere sub-projects diff --git a/microsphere-annotation-processor/pom.xml b/microsphere-annotation-processor/pom.xml index 8db018f0a..6c902f2a2 100644 --- a/microsphere-annotation-processor/pom.xml +++ b/microsphere-annotation-processor/pom.xml @@ -27,13 +27,6 @@ ${revision} - - - org.slf4j - slf4j-api - true - - org.junit.jupiter diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/LoggerUtils.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/LoggerUtils.java index f67986840..c68950336 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/LoggerUtils.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/LoggerUtils.java @@ -18,8 +18,9 @@ -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; + +import io.microsphere.logging.Logger; +import io.microsphere.logging.LoggerFactory; import static java.lang.String.format; diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java index f39658fc6..2396ef772 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java @@ -87,7 +87,7 @@ public void testGetDeclaredFields() { } @Test - public void testGetAllDeclaredFields() { + public void testFindAllDeclaredFields() { TypeElement type = getType(Model.class); List fields = getAllDeclaredFields(type); diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java index 4c639f78d..85d1992aa 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java @@ -66,7 +66,7 @@ public void testDeclaredMethods() { assertEquals(12, methods.size()); methods = getAllDeclaredMethods(type); - assertEquals(34, methods.size()); + assertTrue(methods.size() >= 33); assertTrue(getAllDeclaredMethods((TypeElement) null).isEmpty()); assertTrue(getAllDeclaredMethods((TypeMirror) null).isEmpty()); diff --git a/microsphere-java-core/pom.xml b/microsphere-java-core/pom.xml index dbd1c43bb..9170c96ec 100644 --- a/microsphere-java-core/pom.xml +++ b/microsphere-java-core/pom.xml @@ -20,13 +20,6 @@ - - - javax.annotation - javax.annotation-api - true - - com.google.code.findbugs @@ -34,24 +27,21 @@ true - - - org.apache.commons - commons-lang3 - - - - commons-io - commons-io - - + org.slf4j slf4j-api true + + + commons-logging + commons-logging + true + + org.junit.jupiter @@ -78,6 +68,14 @@ test + + + javax.annotation + javax.annotation-api + test + + + org.springframework spring-core @@ -112,6 +110,20 @@ javax.annotation-api + + + + org.apache.maven.plugins + maven-surefire-plugin + + + --illegal-access=permit + --add-opens java.base/java.lang.invoke=ALL-UNNAMED + + + + + diff --git a/microsphere-java-core/src/main/java/io/microsphere/beans/BeanProperty.java b/microsphere-java-core/src/main/java/io/microsphere/beans/BeanProperty.java index 0c72e21d0..8574c7bb7 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/beans/BeanProperty.java +++ b/microsphere-java-core/src/main/java/io/microsphere/beans/BeanProperty.java @@ -92,12 +92,11 @@ public int hashCode() { @Override public String toString() { - final StringBuilder sb = new StringBuilder("BeanProperty{"); - sb.append("name='").append(name).append('\''); - sb.append(", value=").append(value); - sb.append(", declaringClass=").append(declaringClass); - sb.append(", descriptor=").append(descriptor); - sb.append('}'); - return sb.toString(); + String sb = "BeanProperty{" + "name='" + name + '\'' + + ", value=" + value + + ", declaringClass=" + declaringClass + + ", descriptor=" + descriptor + + '}'; + return sb; } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractArtifactResolver.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractArtifactResolver.java index e09d819a2..83d04fcd6 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractArtifactResolver.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractArtifactResolver.java @@ -1,7 +1,6 @@ package io.microsphere.classloading; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.microsphere.logging.Logger; import java.io.File; import java.io.IOException; @@ -11,6 +10,7 @@ import java.util.LinkedHashSet; import java.util.Set; +import static io.microsphere.logging.LoggerFactory.getLogger; import static io.microsphere.net.URLUtils.resolveArchiveFile; /** @@ -21,7 +21,7 @@ */ public abstract class AbstractArtifactResolver implements ArtifactResolver { - protected final Logger logger = LoggerFactory.getLogger(getClass()); + protected final Logger logger = getLogger(getClass()); private int priority; diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractURLClassPathHandle.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractURLClassPathHandle.java index 968e927c9..b2195729c 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractURLClassPathHandle.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/AbstractURLClassPathHandle.java @@ -17,8 +17,7 @@ package io.microsphere.classloading; import io.microsphere.lang.Prioritized; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.microsphere.logging.Logger; import javax.annotation.Nonnull; import java.lang.reflect.Field; @@ -27,6 +26,7 @@ import java.util.Iterator; import java.util.Objects; +import static io.microsphere.logging.LoggerFactory.getLogger; import static io.microsphere.net.URLUtils.EMPTY_URL_ARRAY; import static io.microsphere.net.URLUtils.resolveBasePath; import static io.microsphere.reflect.FieldUtils.findField; @@ -46,7 +46,7 @@ */ public abstract class AbstractURLClassPathHandle implements URLClassPathHandle, Prioritized { - private final Logger logger = LoggerFactory.getLogger(getClass()); + private final Logger logger = getLogger(getClass()); private Class urlClassPathClass; diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/Artifact.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/Artifact.java index 0f05efdf5..c480961dc 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/Artifact.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/Artifact.java @@ -95,11 +95,10 @@ public int hashCode() { @Override public String toString() { - final StringBuilder sb = new StringBuilder("Artifact{"); - sb.append("artifactId='").append(artifactId).append('\''); - sb.append(", version='").append(version).append('\''); - sb.append(", location='").append(location).append('\''); - sb.append('}'); - return sb.toString(); + String sb = "Artifact{" + "artifactId='" + artifactId + '\'' + + ", version='" + version + '\'' + + ", location='" + location + '\'' + + '}'; + return sb; } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/ArtifactDetector.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/ArtifactDetector.java index dde83ec68..d034d169a 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/ArtifactDetector.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/ArtifactDetector.java @@ -1,9 +1,8 @@ package io.microsphere.classloading; import io.microsphere.collection.CollectionUtils; +import io.microsphere.logging.Logger; import io.microsphere.util.ClassLoaderUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -15,6 +14,7 @@ import java.util.Set; import java.util.StringJoiner; +import static io.microsphere.logging.LoggerFactory.getLogger; import static io.microsphere.net.URLUtils.normalizePath; import static io.microsphere.util.ClassLoaderUtils.getDefaultClassLoader; import static io.microsphere.util.ClassPathUtils.getBootstrapClassPaths; @@ -31,7 +31,7 @@ */ public class ArtifactDetector { - private static final Logger logger = LoggerFactory.getLogger(ArtifactDetector.class); + private static final Logger logger = getLogger(ArtifactDetector.class); private static final String JAVA_HOME_PATH = normalizePath(getProperty("java.home")); diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/BannedArtifactClassLoadingExecutor.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/BannedArtifactClassLoadingExecutor.java index 97d439ff9..e34a09ebb 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/BannedArtifactClassLoadingExecutor.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/BannedArtifactClassLoadingExecutor.java @@ -1,8 +1,7 @@ package io.microsphere.classloading; +import io.microsphere.logging.Logger; import io.microsphere.util.SystemUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.io.BufferedReader; import java.io.IOException; @@ -14,6 +13,7 @@ import java.util.List; import static io.microsphere.constants.SymbolConstants.COLON; +import static io.microsphere.logging.LoggerFactory.getLogger; import static io.microsphere.util.ClassLoaderUtils.removeClassPathURL; import static io.microsphere.util.StringUtils.isBlank; import static io.microsphere.util.StringUtils.split; @@ -40,7 +40,7 @@ public class BannedArtifactClassLoadingExecutor { public static final String CONFIG_LOCATION = "META-INF/banned-artifacts"; - private static final Logger logger = LoggerFactory.getLogger(BannedArtifactClassLoadingExecutor.class); + private static final Logger logger = getLogger(BannedArtifactClassLoadingExecutor.class); private static final String ENCODING = SystemUtils.FILE_ENCODING; @@ -90,7 +90,7 @@ private List loadBannedArtifactConfigs() { private List loadBannedArtifactConfigs(URL configResource) throws IOException { List bannedArtifactConfigs = new LinkedList<>(); try (InputStream inputStream = configResource.openStream(); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, ENCODING)); + BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, ENCODING)) ) { while (true) { String definition = reader.readLine(); diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/MavenArtifact.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/MavenArtifact.java index 10e12000d..fe8424433 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/MavenArtifact.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/MavenArtifact.java @@ -71,12 +71,11 @@ public int hashCode() { @Override public String toString() { - final StringBuilder sb = new StringBuilder("MavenArtifact{"); - sb.append("groupId='").append(groupId).append('\''); - sb.append(", artifactId='").append(getArtifactId()).append('\''); - sb.append(", version='").append(getVersion()).append('\''); - sb.append(", location='").append(getLocation()).append('\''); - sb.append('}'); - return sb.toString(); + String sb = "MavenArtifact{" + "groupId='" + groupId + '\'' + + ", artifactId='" + getArtifactId() + '\'' + + ", version='" + getVersion() + '\'' + + ", location='" + getLocation() + '\'' + + '}'; + return sb; } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/WindowsRedefinedClassLoader.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/WindowsRedefinedClassLoader.java index d9f4f5409..03d82ee70 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/WindowsRedefinedClassLoader.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/WindowsRedefinedClassLoader.java @@ -1,9 +1,7 @@ package io.microsphere.classloading; -import org.apache.commons.io.IOUtils; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import io.microsphere.io.IOUtils; +import io.microsphere.logging.Logger; import java.io.File; import java.io.FileInputStream; @@ -12,6 +10,7 @@ import java.net.URL; import java.net.URLClassLoader; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Enumeration; import java.util.LinkedList; @@ -22,6 +21,11 @@ import java.util.TreeSet; import static io.microsphere.collection.MapUtils.isEmpty; +import static io.microsphere.constants.SeparatorConstants.LINE_SEPARATOR; +import static io.microsphere.io.IOUtils.toByteArray; +import static io.microsphere.logging.LoggerFactory.getLogger; +import static io.microsphere.text.FormatUtils.format; +import static io.microsphere.util.StringUtils.split; /** * The customized ClassLoader under Windows operating system to solve the case-insensitive @@ -34,9 +38,9 @@ class WindowsRedefinedClassLoader extends URLClassLoader { private static final String WINDOWS_REDEFINED_CLASSES_RESOURCE_NAME = "META-INF/windows-redefined-classes"; - private static final Logger logger = LoggerFactory.getLogger(WindowsRedefinedClassLoader.class); + private static final Logger logger = getLogger(WindowsRedefinedClassLoader.class); - private static final Charset charset = Charset.forName("UTF-8"); + private static final Charset charset = StandardCharsets.UTF_8; /** * Class name as key and class resource directory URL as value @@ -76,7 +80,7 @@ private Class loadRedefinedClass(RedefinedClassMetadata metadata, boolean res logger.debug("Class[name: {}] file [name: {}] found in Package directory [path: {}], about to execute ClassLoader.defineClass", className, classFileName, packageDirectory.getAbsolutePath()); try (FileInputStream inputStream = new FileInputStream(classFile)) { - byte[] byteCodes = IOUtils.toByteArray(inputStream); + byte[] byteCodes = toByteArray(inputStream); result = super.defineClass(className, byteCodes, 0, byteCodes.length); } catch (IOException e) { logger.error("Class[name: {}] file [path: {}] cannot be read!", className, classFile.getAbsolutePath()); @@ -153,12 +157,12 @@ private static SortedSet loadRedefinedClassNames(ClassLoader classLoader URL resource = resources.nextElement(); try (InputStream inputStream = resource.openStream()) { String configContent = IOUtils.toString(inputStream, charset); - String[] classNames = StringUtils.split(configContent, System.lineSeparator()); + String[] classNames = split(configContent, LINE_SEPARATOR); redefinedClassNames.addAll(Arrays.asList(classNames)); } } } catch (IOException e) { - throw new IllegalStateException(String.format("Windows redefinition class manifest file] [- S] read failed!", resourceName), e); + throw new IllegalStateException(format("Windows redefinition class manifest file] [- {}] read failed!", resourceName), e); } return redefinedClassNames; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java b/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java index 95a07ad8c..c0684be35 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java @@ -27,7 +27,10 @@ import java.util.function.Consumer; import static io.microsphere.collection.CollectionUtils.size; +import static io.microsphere.collection.CollectionUtils.toIterable; import static io.microsphere.collection.CollectionUtils.toIterator; +import static java.util.Arrays.asList; +import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableList; /** @@ -43,42 +46,51 @@ public static boolean isList(Object values) { return values instanceof List; } - public static List toList(Iterable iterable) { - return toList(iterable.iterator()); + public static List ofList(E... elements) { + return asList(elements); } - public static List toList(Enumeration enumeration) { - return toList(toIterator(enumeration)); + public static List ofList(Iterable iterable) { + if (iterable == null) { + return emptyList(); + } else if (isList(iterable)) { + return (List) iterable; + } else { + return ofList(iterable.iterator()); + } + } + + public static List ofList(Enumeration enumeration) { + return ofList(toIterator(enumeration)); } - public static List toList(Iterator iterator) { + public static List ofList(Iterator iterator) { + if (iterator == null) { + return emptyList(); + } List list = newLinkedList(); while (iterator.hasNext()) { list.add(iterator.next()); } - return list; + return unmodifiableList(list); } - public static List asList(Iterable iterable) { - return asList(iterable.iterator()); - } - - public static List asList(Enumeration enumeration) { - return asList(toIterator(enumeration)); + public static ArrayList newArrayList(int size) { + return new ArrayList<>(size); } - public static List asList(Iterator iterator) { - return unmodifiableList(toList(iterator)); + public static LinkedList newArrayList(Enumeration values) { + return newLinkedList(toIterable(values)); } - public static ArrayList newArrayList(int size) { - return new ArrayList<>(size); + public static ArrayList newArrayList(Iterable values) { + return newArrayList(values.iterator()); } - public static ArrayList newArrayList(Iterable values) { + public static ArrayList newArrayList(Iterator iterator) { ArrayList list = newArrayList(); - for (E value : values) { - list.add(value); + while (iterator.hasNext()) { + list.add(iterator.next()); } return list; } @@ -87,10 +99,18 @@ public static ArrayList newArrayList() { return new ArrayList<>(); } + public static LinkedList newLinkedList(Enumeration values) { + return newLinkedList(toIterable(values)); + } + public static LinkedList newLinkedList(Iterable values) { + return newLinkedList(values.iterator()); + } + + public static LinkedList newLinkedList(Iterator iterator) { LinkedList list = newLinkedList(); - for (E value : values) { - list.add(value); + while (iterator.hasNext()) { + list.add(iterator.next()); } return list; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/collection/MapUtils.java b/microsphere-java-core/src/main/java/io/microsphere/collection/MapUtils.java index b558247ce..831e40415 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/collection/MapUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/collection/MapUtils.java @@ -130,7 +130,7 @@ public static LinkedHashMap newLinkedHashMap(int initialCapacity, } public static LinkedHashMap newLinkedHashMap(Map map) { - return newLinkedHashMap(map); + return new LinkedHashMap(map); } public static ConcurrentHashMap newConcurrentHashMap() { diff --git a/microsphere-java-core/src/main/java/io/microsphere/collection/PropertiesUtils.java b/microsphere-java-core/src/main/java/io/microsphere/collection/PropertiesUtils.java index 02429a812..f4d32c1b7 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/collection/PropertiesUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/collection/PropertiesUtils.java @@ -18,13 +18,13 @@ import io.microsphere.util.BaseUtils; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Properties; import static io.microsphere.collection.MapUtils.isEmpty; import static io.microsphere.constants.SymbolConstants.DOT; +import static java.util.Collections.unmodifiableMap; /** * The utilities class for {@link Properties} @@ -46,7 +46,7 @@ public static Map flatProperties(Map properties) } Map flattenProperties = new LinkedHashMap<>(); flatProperties(properties, null, flattenProperties); - return Collections.unmodifiableMap(flattenProperties); + return unmodifiableMap(flattenProperties); } static void flatProperties(Map properties, String propertyNamePrefix, diff --git a/microsphere-java-core/src/main/java/io/microsphere/collection/SetUtils.java b/microsphere-java-core/src/main/java/io/microsphere/collection/SetUtils.java index f998e686b..ed307d9b3 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/collection/SetUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/collection/SetUtils.java @@ -78,8 +78,8 @@ public static Set of(E... elements) { * @return non-null read-only {@link Set} */ @Nonnull - public static Set asSet(Enumeration elements) { - return asSet(toIterable(elements)); + public static Set ofSet(Enumeration elements) { + return ofSet(toIterable(elements)); } /** @@ -89,7 +89,7 @@ public static Set asSet(Enumeration elements) { * @param the type of elements * @return read-only {@link Set} */ - public static Set asSet(Iterable elements) { + public static Set ofSet(Iterable elements) { return unmodifiableSet(newLinkedHashSet(elements)); } @@ -101,7 +101,7 @@ public static Set asSet(Iterable elements) { * @param the type of elements * @return read-only {@link Set} */ - public static Set asSet(E one, E... others) { + public static Set ofSet(E one, E... others) { int othersSize = length(others); if (othersSize < 1) { return singleton(one); @@ -118,7 +118,7 @@ public static Set asSet(E one, E... others) { return unmodifiableSet(elements); } - public static Set asSet(Collection elements, T... others) { + public static Set ofSet(Collection elements, T... others) { int valuesSize = size(elements); if (valuesSize < 1) { @@ -128,7 +128,7 @@ public static Set asSet(Collection elements, T... others) { int othersSize = length(others); if (othersSize < 1) { - return asSet(elements); + return ofSet(elements); } int size = valuesSize + othersSize; diff --git a/microsphere-java-core/src/main/java/io/microsphere/constants/Constants.java b/microsphere-java-core/src/main/java/io/microsphere/constants/Constants.java index cd174c6ef..3a9e9de33 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/constants/Constants.java +++ b/microsphere-java-core/src/main/java/io/microsphere/constants/Constants.java @@ -11,6 +11,7 @@ * @see Constants * @since 1.0.0 */ -public interface Constants extends FileConstants, PathConstants, ProtocolConstants, SeparatorConstants, SymbolConstants { +public interface Constants extends FileConstants, PathConstants, PropertyConstants, + ProtocolConstants, SeparatorConstants, SymbolConstants { } diff --git a/microsphere-java-core/src/main/java/io/microsphere/constants/FileConstants.java b/microsphere-java-core/src/main/java/io/microsphere/constants/FileConstants.java index d642c8c51..f996dd902 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/constants/FileConstants.java +++ b/microsphere-java-core/src/main/java/io/microsphere/constants/FileConstants.java @@ -4,6 +4,7 @@ package io.microsphere.constants; import static io.microsphere.constants.SymbolConstants.DOT; +import static io.microsphere.constants.SymbolConstants.DOT_CHAR; /** * File Constants @@ -39,29 +40,38 @@ public interface FileConstants { */ String CLASS = "class"; + /** + * File extension character + */ + char FILE_EXTENSION_CHAR = DOT_CHAR; + + /** + * File extension separator + */ + String FILE_EXTENSION = DOT; /** * Zip File extension : ".zip" */ - String ZIP_EXTENSION = DOT + ZIP; + String ZIP_EXTENSION = FILE_EXTENSION + ZIP; /** * Jar File extension : ".jar" */ - String JAR_EXTENSION = DOT + JAR; + String JAR_EXTENSION = FILE_EXTENSION + JAR; /** * War File extension : ".jar" */ - String WAR_EXTENSION = DOT + WAR; + String WAR_EXTENSION = FILE_EXTENSION + WAR; /** * Ear File extension : ".jar" */ - String EAR_EXTENSION = DOT + EAR; + String EAR_EXTENSION = FILE_EXTENSION + EAR; /** * Class File extension : ".class" */ - String CLASS_EXTENSION = DOT + CLASS; + String CLASS_EXTENSION = FILE_EXTENSION + CLASS; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/PropertiesToStringConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/PropertiesToStringConverter.java index e6ba54d97..85cc8138f 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/PropertiesToStringConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/PropertiesToStringConverter.java @@ -16,9 +16,8 @@ */ package io.microsphere.convert; -import org.apache.commons.io.output.StringBuilderWriter; - import java.io.IOException; +import java.io.StringWriter; import java.util.Properties; /** @@ -33,7 +32,7 @@ public class PropertiesToStringConverter implements Converterchar[] diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToCharacterConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToCharacterConverter.java index 2c8ba1dfe..d7d2a2c9d 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToCharacterConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToCharacterConverter.java @@ -17,7 +17,7 @@ package io.microsphere.convert; -import static org.apache.commons.lang3.StringUtils.length; +import static io.microsphere.util.StringUtils.length; /** * The class to convert {@link String} to {@link Character} diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToDoubleConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToDoubleConverter.java index 1a66a30a6..e1c3e461f 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToDoubleConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToDoubleConverter.java @@ -16,8 +16,8 @@ */ package io.microsphere.convert; +import static io.microsphere.util.StringUtils.isNotEmpty; import static java.lang.Double.valueOf; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; /** * The class to convert {@link String} to {@link Double} diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToFloatConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToFloatConverter.java index b9fde2b2b..10b1f9e8b 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToFloatConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToFloatConverter.java @@ -16,8 +16,8 @@ */ package io.microsphere.convert; +import static io.microsphere.util.StringUtils.isNotEmpty; import static java.lang.Float.valueOf; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; /** * The class to convert {@link String} to {@link Float} diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToIntegerConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToIntegerConverter.java index 8948c5089..64d4cbe34 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToIntegerConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToIntegerConverter.java @@ -16,8 +16,8 @@ */ package io.microsphere.convert; +import static io.microsphere.util.StringUtils.isNotEmpty; import static java.lang.Integer.valueOf; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; /** * The class to convert {@link String} to {@link Integer} diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToLongConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToLongConverter.java index 244d586a5..30a2b5cf9 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToLongConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToLongConverter.java @@ -16,8 +16,8 @@ */ package io.microsphere.convert; +import static io.microsphere.util.StringUtils.isNotEmpty; import static java.lang.Long.valueOf; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; /** * The class to convert {@link String} to {@link Long} diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToShortConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToShortConverter.java index 19f27c402..830064b9e 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/StringToShortConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/StringToShortConverter.java @@ -16,8 +16,8 @@ */ package io.microsphere.convert; +import static io.microsphere.util.StringUtils.isNotEmpty; import static java.lang.Short.valueOf; -import static org.apache.commons.lang3.StringUtils.isNotEmpty; /** * The class to convert {@link String} to {@link Short} diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToArrayConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToArrayConverter.java index 4b8aa4063..d3a7ad6a0 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToArrayConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToArrayConverter.java @@ -31,10 +31,7 @@ public class StringToArrayConverter implements StringToMultiValueConverter { public boolean accept(Class type, Class multiValueType) { - if (multiValueType != null && multiValueType.isArray()) { - return true; - } - return false; + return multiValueType != null && multiValueType.isArray(); } @Override diff --git a/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToMultiValueConverter.java b/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToMultiValueConverter.java index 7c8c01ef2..2cd6adcc7 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToMultiValueConverter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/convert/multiple/StringToMultiValueConverter.java @@ -16,10 +16,11 @@ */ package io.microsphere.convert.multiple; -import org.apache.commons.lang3.ArrayUtils; -import static org.apache.commons.lang3.StringUtils.isEmpty; -import static org.apache.commons.lang3.StringUtils.split; +import io.microsphere.util.ArrayUtils; + +import static io.microsphere.util.StringUtils.isEmpty; +import static io.microsphere.util.StringUtils.split; /** * The class to convert {@link String} to multiple value object diff --git a/microsphere-java-core/src/main/java/io/microsphere/filter/ClassFilter.java b/microsphere-java-core/src/main/java/io/microsphere/filter/ClassFilter.java index 8884e2e12..c1d237462 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/filter/ClassFilter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/filter/ClassFilter.java @@ -1,5 +1,5 @@ /** - * + * */ package io.microsphere.filter; diff --git a/microsphere-java-core/src/main/java/io/microsphere/filter/Filter.java b/microsphere-java-core/src/main/java/io/microsphere/filter/Filter.java index 658c20ebc..55ce46760 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/filter/Filter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/filter/Filter.java @@ -6,8 +6,7 @@ /** * {@link Filter} interface * - * @param - * the type of Filtered object + * @param the type of Filtered object * @author Mercy * @version 1.0.0 * @see Filter @@ -18,8 +17,7 @@ public interface Filter { /** * Does accept filtered object? * - * @param filteredObject - * filtered object + * @param filteredObject filtered object * @return */ boolean accept(T filteredObject); diff --git a/microsphere-java-core/src/main/java/io/microsphere/filter/FilterUtils.java b/microsphere-java-core/src/main/java/io/microsphere/filter/FilterUtils.java index dbc16272a..57ce4a667 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/filter/FilterUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/filter/FilterUtils.java @@ -1,14 +1,15 @@ /** - * + * */ package io.microsphere.filter; import javax.annotation.Nonnull; import java.util.ArrayList; -import java.util.Collections; import java.util.Iterator; import java.util.List; +import static java.util.Collections.unmodifiableList; + /** * {@link Filter} utility class * @@ -56,6 +57,6 @@ public static List filter(Iterable iterable, FilterOperator filterOper list.add(element); } } - return Collections.unmodifiableList(list); + return unmodifiableList(list); } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassFilter.java b/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassFilter.java index 0f4c7fc49..e56dab3d2 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassFilter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassFilter.java @@ -1,5 +1,5 @@ /** - * + * */ package io.microsphere.filter; diff --git a/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassNameFilter.java b/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassNameFilter.java index e8648b8d9..cd2d37133 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassNameFilter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/filter/PackageNameClassNameFilter.java @@ -1,5 +1,5 @@ /** - * + * */ package io.microsphere.filter; diff --git a/microsphere-java-core/src/main/java/io/microsphere/filter/TrueClassFilter.java b/microsphere-java-core/src/main/java/io/microsphere/filter/TrueClassFilter.java index cf8009fcd..6e5b9ccb8 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/filter/TrueClassFilter.java +++ b/microsphere-java-core/src/main/java/io/microsphere/filter/TrueClassFilter.java @@ -1,5 +1,5 @@ /** - * + * */ package io.microsphere.filter; diff --git a/microsphere-java-core/src/main/java/io/microsphere/invoke/MethodHandleUtils.java b/microsphere-java-core/src/main/java/io/microsphere/invoke/MethodHandleUtils.java index a7cd33c61..d9e02ecee 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/invoke/MethodHandleUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/invoke/MethodHandleUtils.java @@ -16,6 +16,7 @@ */ package io.microsphere.invoke; +import io.microsphere.lang.function.ThrowableBiFunction; import io.microsphere.util.BaseUtils; import java.lang.invoke.MethodHandle; @@ -23,20 +24,22 @@ import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import java.lang.reflect.Modifier; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static io.microsphere.invoke.MethodHandleUtils.LookupKey.buildKey; import static io.microsphere.invoke.MethodHandleUtils.LookupMode.getModes; -import static io.microsphere.lang.function.ThrowableSupplier.execute; +import static io.microsphere.lang.function.ThrowableBiFunction.execute; +import static io.microsphere.reflect.ConstructorUtils.findConstructor; import static io.microsphere.reflect.ConstructorUtils.getDeclaredConstructor; import static io.microsphere.reflect.ConstructorUtils.newInstance; +import static io.microsphere.reflect.MemberUtils.isPublic; import static io.microsphere.reflect.MethodUtils.findMethod; -import static java.lang.invoke.MethodHandles.Lookup.PACKAGE; -import static java.lang.invoke.MethodHandles.Lookup.PRIVATE; -import static java.lang.invoke.MethodHandles.Lookup.PROTECTED; -import static java.lang.invoke.MethodHandles.Lookup.PUBLIC; +import static io.microsphere.reflect.MethodUtils.isCallerSensitiveMethod; +import static io.microsphere.util.ArrayUtils.isEmpty; +import static java.lang.invoke.MethodHandles.publicLookup; import static java.lang.invoke.MethodType.methodType; /** @@ -47,15 +50,132 @@ */ public abstract class MethodHandleUtils extends BaseUtils { + /** + * A single-bit mask representing {@code public} access, + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value, {@code 0x01}, happens to be the same as the value of the + * {@code public} {@linkplain Modifier#PUBLIC modifier bit}. + *

+ * A {@code Lookup} with this lookup mode performs cross-module access check + * with respect to the {@linkplain MethodHandles.Lookup#lookupClass() lookup class} and + * {@linkplain MethodHandles.Lookup#previousLookupClass() previous lookup class} if present. + * + * @see MethodHandles.Lookup#PUBLIC + */ + public static final int PUBLIC = Modifier.PUBLIC; + + /** + * A single-bit mask representing {@code private} access, + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value, {@code 0x02}, happens to be the same as the value of the + * {@code private} {@linkplain Modifier#PRIVATE modifier bit}. + * + * @see MethodHandles.Lookup#PRIVATE + */ + public static final int PRIVATE = Modifier.PRIVATE; + + /** + * A single-bit mask representing {@code protected} access, + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value, {@code 0x04}, happens to be the same as the value of the + * {@code protected} {@linkplain Modifier#PROTECTED modifier bit}. + * + * @see MethodHandles.Lookup#PROTECTED + */ + public static final int PROTECTED = Modifier.PROTECTED; + + /** + * A single-bit mask representing {@code package} access (default access), + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value is {@code 0x08}, which does not correspond meaningfully to + * any particular {@linkplain Modifier modifier bit}. + * + * @see MethodHandles.Lookup#PACKAGE + */ + public static final int PACKAGE = Modifier.STATIC; + + /** + * A single-bit mask representing {@code module} access, + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value is {@code 0x10}, which does not correspond meaningfully to + * any particular {@linkplain Modifier modifier bit}. + * In conjunction with the {@code PUBLIC} modifier bit, a {@code Lookup} + * with this lookup mode can access all public types in the module of the + * lookup class and public types in packages exported by other modules + * to the module of the lookup class. + *

+ * If this lookup mode is set, the {@linkplain MethodHandles.Lookup#previousLookupClass() + * previous lookup class} is always {@code null}. + * + * @see MethodHandles.Lookup#MODULE + * @since 9 + */ + public static final int MODULE = PACKAGE << 1; + + /** + * A single-bit mask representing {@code unconditional} access + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value is {@code 0x20}, which does not correspond meaningfully to + * any particular {@linkplain Modifier modifier bit}. + * A {@code Lookup} with this lookup mode assumes {@linkplain + * java.lang.Module#canRead(java.lang.Module) readability}. + * This lookup mode can access all public members of public types + * of all modules when the type is in a package that is {@link + * java.lang.Module#isExported(String) exported unconditionally}. + * + *

+ * If this lookup mode is set, the {@linkplain MethodHandles.Lookup#previousLookupClass() + * previous lookup class} is always {@code null}. + * + * @see MethodHandles.Lookup#publicLookup() + * @see MethodHandles.Lookup#UNCONDITIONAL + * @since 9 + */ + public static final int UNCONDITIONAL = PACKAGE << 2; + + /** + * A single-bit mask representing {@code original} access + * which may contribute to the result of {@link MethodHandles.Lookup#lookupModes lookupModes}. + * The value is {@code 0x40}, which does not correspond meaningfully to + * any particular {@linkplain Modifier modifier bit}. + * + *

+ * If this lookup mode is set, the {@code Lookup} object must be + * created by the original lookup class by calling + * {@link MethodHandles#lookup()} method or by a bootstrap method + * invoked by the VM. The {@code Lookup} object with this lookup + * mode has {@linkplain MethodHandles.Lookup#hasFullPrivilegeAccess() full privilege access}. + * + * @see MethodHandles.Lookup#ORIGINAL + * @since 16 + */ + public static final int ORIGINAL = PACKAGE << 3; + /** * A single-bit mask representing all accesses (public, private, protected and package) * The value, 0x0f, happens to be the same as the value of the modifier bit. */ - public static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE); + public static final int ALL_MODES = (PUBLIC | PRIVATE | PROTECTED | PACKAGE | MODULE | UNCONDITIONAL | ORIGINAL); + + /** + * {@link MethodHandle} for Not-Found + */ + public static final MethodHandle NOT_FOUND_METHOD_HANDLE = null; + /** + * The {@link Constructor} for {@link MethodHandles.Lookup#Lookup(Class)} since JDK 7 + */ private static final Constructor lookupConstructor1 = getDeclaredConstructor(MethodHandles.Lookup.class, Class.class); - private static final Constructor lookupConstructor2 = getDeclaredConstructor(MethodHandles.Lookup.class, Class.class, int.class); + /** + * The {@link Constructor} for {@link MethodHandles.Lookup#Lookup(Class, int)} since JDK 7 + */ + private static final Constructor lookupConstructor2 = findConstructor(MethodHandles.Lookup.class, Class.class, int.class); + + /** + * The {@link Constructor} for {@link MethodHandles.Lookup#Lookup(Class, Class, int)} since JDK 14 + */ + private static final Constructor lookupConstructor3 = findConstructor(MethodHandles.Lookup.class, Class.class, Class.class, int.class); private static final ConcurrentMap lookupCache = new ConcurrentHashMap<>(); @@ -66,39 +186,49 @@ public abstract class MethodHandleUtils extends BaseUtils { * @see MethodHandles.Lookup#PRIVATE * @see MethodHandles.Lookup#PROTECTED * @see MethodHandles.Lookup#PACKAGE + * @see MethodHandles.Lookup#MODULE + * @see MethodHandles.Lookup#UNCONDITIONAL + * @see MethodHandles.Lookup#ORIGINAL * @see MethodHandles.Lookup#TRUSTED * @see MethodHandles.Lookup#ALL_MODES */ - public static enum LookupMode { + public enum LookupMode { + + + /** + * @see MethodHandleUtils#PUBLIC + */ + PUBLIC(MethodHandleUtils.PUBLIC), + /** + * @see MethodHandleUtils#PRIVATE + */ + PRIVATE(MethodHandleUtils.PRIVATE), + + /** + * @see MethodHandleUtils#PROTECTED + */ + PROTECTED(MethodHandleUtils.PROTECTED), /** - * A single-bit mask representing {@code public} access, - * The value is {@code 0x01}, happens to be the same as the value of the - * {@code public} {@linkplain java.lang.reflect.Modifier#PUBLIC modifier bit}. + * @see MethodHandleUtils#PACKAGE */ - PUBLIC(MethodHandles.Lookup.PUBLIC), + PACKAGE(MethodHandleUtils.PACKAGE), /** - * A single-bit mask representing {@code private} access, - * The value is {@code 0x02}, happens to be the same as the value of the - * {@code public} {@linkplain java.lang.reflect.Modifier#PRIVATE modifier bit}. + * @see MethodHandleUtils#MODULE */ - PRIVATE(MethodHandles.Lookup.PRIVATE), + MODULE(MethodHandleUtils.MODULE), /** - * A single-bit mask representing {@code protected} access, - * The value is {@code 0x04}, happens to be the same as the value of the - * {@code public} {@linkplain java.lang.reflect.Modifier#PROTECTED modifier bit}. + * @see MethodHandleUtils#UNCONDITIONAL */ - PROTECTED(MethodHandles.Lookup.PROTECTED), + UNCONDITIONAL(MethodHandleUtils.UNCONDITIONAL), /** - * A single-bit mask representing {@code package} access (default access), - * The value is {@code 0x08}, which does not correspond meaningfully to - * any particular {@linkplain java.lang.reflect.Modifier modifier bit}. + * @see MethodHandleUtils#ORIGINAL */ - PACKAGE(MethodHandles.Lookup.PACKAGE), + ORIGINAL(MethodHandleUtils.ORIGINAL), /** * A single-bit mask representing all accesses (public, private, protected and package) @@ -186,19 +316,47 @@ public static MethodHandles.Lookup lookup(Class lookupClass, LookupMode... lo /** * The convenient method to find {@link MethodHandles.Lookup#findVirtual(Class, String, MethodType)} * - * @param lookupClass - * @param methodName - * @param parameterTypes - * @return + * @param lookupClass the class to be looked up + * @param methodName the target method name + * @param parameterTypes the types of target method parameters + * @return {@link MethodHandle} */ public static MethodHandle findVirtual(Class lookupClass, String methodName, Class... parameterTypes) { + return find(lookupClass, methodName, parameterTypes, (lookup, methodType) -> lookup.findVirtual(lookupClass, methodName, methodType)); + } + + /** + * The convenient method to find {@link MethodHandles.Lookup#findStatic(Class, String, MethodType)} + * + * @param lookupClass the class to be looked up + * @param methodName the target method name + * @param parameterTypes the types of target method parameters + * @return {@link MethodHandle} + */ + public static MethodHandle findStatic(Class lookupClass, String methodName, Class... parameterTypes) { + return find(lookupClass, methodName, parameterTypes, (lookup, methodType) -> lookup.findStatic(lookupClass, methodName, methodType)); + } + + protected static MethodHandle find(Class lookupClass, String methodName, Class[] parameterTypes, + ThrowableBiFunction function) { Method method = findMethod(lookupClass, methodName, parameterTypes); - MethodType methodType = methodType(method.getReturnType(), parameterTypes); - MethodHandles.Lookup lookup = lookup(lookupClass); - return execute(() -> lookup.findVirtual(lookupClass, methodName, methodType)); + if (method == null) { + return NOT_FOUND_METHOD_HANDLE; + } + Class returnType = method.getReturnType(); + MethodType methodType = isEmpty(parameterTypes) ? methodType(returnType) : methodType(returnType, parameterTypes); + MethodHandles.Lookup lookup = isiCandidateMethod(method) ? publicLookup() : lookup(lookupClass); + return execute(lookup, methodType, function); + } + + private static boolean isiCandidateMethod(Method method) { + return isPublic(method) && !isCallerSensitiveMethod(method); } private static MethodHandles.Lookup newLookup(LookupKey key) { + if (lookupConstructor3 != null) { + return newInstance(lookupConstructor3, key.lookupClass, key.lookupClass, key.allowedModes); + } return newInstance(lookupConstructor2, key.lookupClass, key.allowedModes); } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/FastByteArrayInputStream.java b/microsphere-java-core/src/main/java/io/microsphere/io/FastByteArrayInputStream.java index e7f0c040d..4f0c70ba8 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/FastByteArrayInputStream.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/FastByteArrayInputStream.java @@ -39,7 +39,7 @@ public class FastByteArrayInputStream extends ByteArrayInputStream { * * @param buf the input buffer. */ - public FastByteArrayInputStream(byte buf[]) { + public FastByteArrayInputStream(byte[] buf) { super(buf); } @@ -57,7 +57,7 @@ public FastByteArrayInputStream(byte buf[]) { * @param offset the offset in the buffer of the first byte to read. * @param length the maximum number of bytes to read from the buffer. */ - public FastByteArrayInputStream(byte buf[], int offset, int length) { + public FastByteArrayInputStream(byte[] buf, int offset, int length) { super(buf, offset, length); } @@ -67,7 +67,7 @@ public int read() { } @Override - public int read(byte b[], int off, int len) { + public int read(byte[] b, int off, int len) { if (b == null) { throw new NullPointerException(); } else if (off < 0 || len < 0 || len > b.length - off) { diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/FileUtils.java b/microsphere-java-core/src/main/java/io/microsphere/io/FileUtils.java index 58bbd752b..7c19f4263 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/FileUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/FileUtils.java @@ -3,11 +3,15 @@ */ package io.microsphere.io; -import io.microsphere.net.URLUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.SystemUtils; - import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +import static io.microsphere.constants.FileConstants.FILE_EXTENSION_CHAR; +import static io.microsphere.constants.SeparatorConstants.FILE_SEPARATOR; +import static io.microsphere.net.URLUtils.normalizePath; +import static io.microsphere.util.StringUtils.replace; +import static io.microsphere.util.SystemUtils.IS_OS_WINDOWS; /** * {@link File} Utility @@ -22,10 +26,8 @@ public abstract class FileUtils { /** * Resolve Relative Path * - * @param parentDirectory - * Parent Directory - * @param targetFile - * Target File + * @param parentDirectory Parent Directory + * @param targetFile Target File * @return If targetFile is a sub-file of parentDirectory , resolve relative path, or * null * @since 1.0.0 @@ -36,6 +38,203 @@ public static String resolveRelativePath(File parentDirectory, File targetFile) if (!targetFilePath.contains(parentDirectoryPath)) { return null; } - return URLUtils.normalizePath(StringUtils.replace(targetFilePath, parentDirectoryPath, SystemUtils.FILE_SEPARATOR)); + return normalizePath(replace(targetFilePath, parentDirectoryPath, FILE_SEPARATOR)); + } + + /** + * Get File Extension + * + * @param fileName the name of {@link File} + * @return the file extension if found + */ + public static String getFileExtension(String fileName) { + if (fileName == null) { + return null; + } + int index = fileName.lastIndexOf(FILE_EXTENSION_CHAR); + return index > -1 ? fileName.substring(index + 1) : null; + } + + /** + * Deletes a directory recursively. + * + * @param directory directory to delete + * @throws IOException in case deletion is unsuccessful + */ + public static void deleteDirectory(File directory) throws IOException { + if (!directory.exists()) { + return; + } + + if (!isSymlink(directory)) { + cleanDirectory(directory); + } + + if (!directory.delete()) { + String message = + "Unable to delete directory " + directory + "."; + throw new IOException(message); + } + } + + + /** + * Cleans a directory without deleting it. + * + * @param directory directory to clean + * @throws IOException in case cleaning is unsuccessful + */ + public static void cleanDirectory(File directory) throws IOException { + if (!directory.exists()) { + String message = directory + " does not exist"; + throw new IllegalArgumentException(message); + } + + if (!directory.isDirectory()) { + String message = directory + " is not a directory"; + throw new IllegalArgumentException(message); + } + + File[] files = directory.listFiles(); + if (files == null) { // null if security restricted + throw new IOException("Failed to list contents of " + directory); + } + + IOException exception = null; + for (File file : files) { + try { + forceDelete(file); + } catch (IOException ioe) { + exception = ioe; + } + } + + if (null != exception) { + throw exception; + } + } + + /** + * Deletes a file. If file is a directory, delete it and all sub-directories. + *

+ * The difference between File.delete() and this method are: + *

    + *
  • A directory to be deleted does not have to be empty.
  • + *
  • You get exceptions when a file or directory cannot be deleted. + * (java.io.File methods returns a boolean)
  • + *
+ * + * @param file file or directory to delete, must not be {@code null} + * @throws NullPointerException if the directory is {@code null} + * @throws FileNotFoundException if the file was not found + * @throws IOException in case deletion is unsuccessful + */ + public static void forceDelete(File file) throws IOException { + if (file.isDirectory()) { + deleteDirectory(file); + } else { + boolean filePresent = file.exists(); + if (!file.delete()) { + if (!filePresent) { + throw new FileNotFoundException("File does not exist: " + file); + } + String message = + "Unable to delete file: " + file; + throw new IOException(message); + } + } + } + + /** + * Schedules a file to be deleted when JVM exits. + * If file is directory delete it and all sub-directories. + * + * @param file file or directory to delete, must not be {@code null} + * @throws NullPointerException if the file is {@code null} + * @throws IOException in case deletion is unsuccessful + */ + public static void forceDeleteOnExit(File file) throws IOException { + if (file.isDirectory()) { + deleteDirectoryOnExit(file); + } else { + file.deleteOnExit(); + } + } + + /** + * Schedules a directory recursively for deletion on JVM exit. + * + * @param directory directory to delete, must not be {@code null} + * @throws NullPointerException if the directory is {@code null} + * @throws IOException in case deletion is unsuccessful + */ + private static void deleteDirectoryOnExit(File directory) throws IOException { + if (!directory.exists()) { + return; + } + + directory.deleteOnExit(); + if (!isSymlink(directory)) { + cleanDirectoryOnExit(directory); + } + } + + /** + * Cleans a directory without deleting it. + * + * @param directory directory to clean, must not be {@code null} + * @throws NullPointerException if the directory is {@code null} + * @throws IOException in case cleaning is unsuccessful + */ + private static void cleanDirectoryOnExit(File directory) throws IOException { + if (!directory.exists()) { + String message = directory + " does not exist"; + throw new IllegalArgumentException(message); + } + + if (!directory.isDirectory()) { + String message = directory + " is not a directory"; + throw new IllegalArgumentException(message); + } + + File[] files = directory.listFiles(); + if (files == null) { // null if security restricted + throw new IOException("Failed to list contents of " + directory); + } + + IOException exception = null; + for (File file : files) { + try { + forceDeleteOnExit(file); + } catch (IOException ioe) { + exception = ioe; + } + } + + if (null != exception) { + throw exception; + } + } + + public static boolean isSymlink(File file) throws IOException { + if (file == null) { + throw new NullPointerException("File must not be null"); + } + if (IS_OS_WINDOWS) { + return false; + } + File fileInCanonicalDir = null; + if (file.getParent() == null) { + fileInCanonicalDir = file; + } else { + File canonicalDir = file.getParentFile().getCanonicalFile(); + fileInCanonicalDir = new File(canonicalDir, file.getName()); + } + + if (fileInCanonicalDir.getCanonicalFile().equals(fileInCanonicalDir.getAbsoluteFile())) { + return false; + } else { + return true; + } } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java b/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java new file mode 100644 index 000000000..598b49d3d --- /dev/null +++ b/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java @@ -0,0 +1,168 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microsphere.io; + +import io.microsphere.util.BaseUtils; +import io.microsphere.util.SystemUtils; + +import java.io.ByteArrayOutputStream; +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; + +import static io.microsphere.util.ArrayUtils.EMPTY_BYTE_ARRAY; +import static io.microsphere.util.StringUtils.isBlank; +import static io.microsphere.util.SystemUtils.FILE_ENCODING; +import static java.lang.Integer.getInteger; +import static java.nio.charset.Charset.forName; +import static java.util.Objects.requireNonNull; + +/** + * The utilities class for I/O + * + * @author
Mercy + * @see Files + * @see Paths + * @since 1.0.0 + */ +public abstract class IOUtils extends BaseUtils { + + /** + * The buffer size for I/O + */ + public static final int BUFFER_SIZE = getInteger("microsphere.io.buffer.size", 4096); + + /** + * Copy the contents of the given InputStream into a new byte array. + *

Leaves the stream open when done. + * + * @param in the stream to copy from (may be {@code null} or empty) + * @return the new byte array that has been copied to (possibly empty) + * @throws IOException in case of I/O errors + */ + public static byte[] toByteArray(InputStream in) throws IOException { + if (in == null) { + return EMPTY_BYTE_ARRAY; + } + ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE); + copy(in, out); + return out.toByteArray(); + } + + /** + * Copy the contents of the given InputStream into a new {@link String}. + *

Leaves the stream open when done. + * + * @param in the stream to copy from (may be {@code null} or empty) + * @param encoding the encoding to use, if it's null, take the {@link SystemUtils#FILE_ENCODING} as default + * @return the new byte array that has been copied to (possibly empty) + * @throws IOException in case of I/O errors + */ + public static String toString(InputStream in, String encoding) throws IOException { + String charset = isBlank(encoding) ? FILE_ENCODING : encoding; + return toString(in, forName(charset)); + } + + /** + * Copy the contents of the given InputStream into a new {@link String}. + *

Leaves the stream open when done. + * + * @param in the stream to copy from (may be {@code null} or empty) + * @param charset the charset to use, if it's null, take the {@link SystemUtils#FILE_ENCODING} as default + * @return the new byte array that has been copied to (possibly empty) + * @throws IOException in case of I/O errors + */ + public static String toString(InputStream in, Charset charset) throws IOException { + byte[] bytes = toByteArray(in); + Charset actualCharset = charset == null ? StandardCharsets.UTF_8 : charset; + return EMPTY_BYTE_ARRAY.equals(bytes) ? null : new String(bytes, actualCharset); + } + + /** + * Copy the contents of the given InputStream to the given OutputStream. + *

Leaves both streams open when done. + * + * @param in the InputStream to copy from + * @param out the OutputStream to copy to + * @return the number of bytes copied + * @throws IOException in case of I/O errors + */ + public static int copy(InputStream in, OutputStream out) throws IOException { + requireNonNull(in, "No InputStream specified"); + requireNonNull(out, "No OutputStream specified"); + + int byteCount = 0; + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead; + while ((bytesRead = in.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + byteCount += bytesRead; + } + out.flush(); + return byteCount; + } + + /** + * Closes a URLConnection. + * + * @param conn the connection to close. + */ + public static void close(URLConnection conn) { + if (conn instanceof HttpURLConnection) { + ((HttpURLConnection) conn).disconnect(); + } + } + + /** + * Unconditionally close a Closeable. + *

+ * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored. + * This is typically used in finally blocks. + *

+ * Example code: + *

+     *   Closeable closeable = null;
+     *   try {
+     *       closeable = new FileReader("foo.txt");
+     *       // process closeable
+     *       closeable.close();
+     *   } catch (Exception e) {
+     *       // error handling
+     *   } finally {
+     *       IOUtils.closeQuietly(closeable);
+     *   }
+     * 
+ * + * @param closeable the object to close, may be null or already closed + */ + public static void close(Closeable closeable) { + try { + if (closeable != null) { + closeable.close(); + } + } catch (IOException ignored) { + // ignore + } + } +} diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/event/FileChangedEvent.java b/microsphere-java-core/src/main/java/io/microsphere/io/event/FileChangedEvent.java index 52255aca4..0982f3e89 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/event/FileChangedEvent.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/event/FileChangedEvent.java @@ -64,17 +64,16 @@ public Kind getKind() { @Override public String toString() { - final StringBuilder sb = new StringBuilder("FileChangedEvent{"); - sb.append("kind=").append(kind); - sb.append(", file=").append(getFile()); - sb.append('}'); - return sb.toString(); + String sb = "FileChangedEvent{" + "kind=" + kind + + ", file=" + getFile() + + '}'; + return sb; } /** * The Kind of File Changed Event */ - public static enum Kind { + public enum Kind { /** * The file or directory entry created @@ -89,6 +88,6 @@ public static enum Kind { /** * The file or directory entry deleted */ - DELETED; + DELETED } } diff --git a/microsphere-jdk-tools/src/test/java/io/microsphere/tools/CompilerTest.java b/microsphere-java-core/src/main/java/io/microsphere/io/filter/DirectoryFileFilter.java similarity index 59% rename from microsphere-jdk-tools/src/test/java/io/microsphere/tools/CompilerTest.java rename to microsphere-java-core/src/main/java/io/microsphere/io/filter/DirectoryFileFilter.java index af5b82084..b501a55c0 100644 --- a/microsphere-jdk-tools/src/test/java/io/microsphere/tools/CompilerTest.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/filter/DirectoryFileFilter.java @@ -14,22 +14,30 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package io.microsphere.tools; +package io.microsphere.io.filter; -import io.microsphere.tools.attach.LocalVirtualMachineTemplateTest; -import org.junit.jupiter.api.Test; - -import java.io.IOException; +import java.io.File; /** - * The Compiler test case + * This filter accepts Files that are directories. + * + * @author
Mercy + * @see IOFileFilter + * @since 1.0.0 */ -public class CompilerTest { +public class DirectoryFileFilter implements IOFileFilter { + + /** + * Singleton instance of {@link DirectoryFileFilter}. + */ + public static final DirectoryFileFilter INSTANCE = new DirectoryFileFilter(); + - @Test - public void testCompile() throws IOException { - Compiler compiler = new Compiler(); - compiler.compile(LocalVirtualMachineTemplateTest.class); + protected DirectoryFileFilter() { } -} + @Override + public boolean accept(File file) { + return file.isDirectory(); + } +} diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/filter/FileExtensionFilter.java b/microsphere-java-core/src/main/java/io/microsphere/io/filter/FileExtensionFilter.java new file mode 100644 index 000000000..575c4858c --- /dev/null +++ b/microsphere-java-core/src/main/java/io/microsphere/io/filter/FileExtensionFilter.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microsphere.io.filter; + +import io.microsphere.io.FileUtils; + +import java.io.File; + +import static io.microsphere.io.FileUtils.getFileExtension; +import static io.microsphere.util.StringUtils.isBlank; +import static io.microsphere.util.SystemUtils.IS_OS_WINDOWS; + +/** + * {@link IOFileFilter} for file extension filter + * + * @author Mercy + * @see IOFileFilter + * @see FileUtils#getFileExtension(String) + * @since 1.0.0 + */ +public class FileExtensionFilter implements IOFileFilter { + + private final String extension; + + protected FileExtensionFilter(String extension) { + this.extension = extension; + } + + @Override + public boolean accept(File file) { + if (file == null || file.isDirectory()) { + return false; + } + + String fileName = file.getName(); + String fileExtension = getFileExtension(fileName); + if (isBlank(fileExtension)) { + return false; + } + + return IS_OS_WINDOWS ? fileExtension.equalsIgnoreCase(extension) : fileExtension.equals(extension); + } + + /** + * Creates an instance of {@link FileExtensionFilter} by the given file extension + * + * @param extension the file extension + * @return non-null + */ + public static FileExtensionFilter of(String extension) { + return new FileExtensionFilter(extension); + } +} diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/filter/IOFileFilter.java b/microsphere-java-core/src/main/java/io/microsphere/io/filter/IOFileFilter.java new file mode 100644 index 000000000..660a799e4 --- /dev/null +++ b/microsphere-java-core/src/main/java/io/microsphere/io/filter/IOFileFilter.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microsphere.io.filter; + +import io.microsphere.filter.Filter; + +import java.io.File; +import java.io.FileFilter; +import java.io.FilenameFilter; + +/** + * An interface which brings the {@link FileFilter} and {@link FilenameFilter} + * interfaces together. + * + * @see FileFilter + * @see FilenameFilter + * @see Filter + * @since 1.0.0 + */ +@FunctionalInterface +public interface IOFileFilter extends FileFilter, FilenameFilter { + + @Override + boolean accept(File file); + + @Override + default boolean accept(File dir, String name) { + return accept(new File(dir, name)); + } +} diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/filter/NameFileFilter.java b/microsphere-java-core/src/main/java/io/microsphere/io/filter/NameFileFilter.java new file mode 100644 index 000000000..1e53e2231 --- /dev/null +++ b/microsphere-java-core/src/main/java/io/microsphere/io/filter/NameFileFilter.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microsphere.io.filter; + +import java.io.File; + +/** + * Filters filenames for a certain name. + * + * @author Mercy + * @see IOFileFilter + * @since 1.0.0 + */ +public class NameFileFilter implements IOFileFilter { + + private final String name; + + private final boolean caseSensitive; + + public NameFileFilter(String name) { + this(name, true); + } + + public NameFileFilter(String name, boolean caseSensitive) { + this.name = name; + this.caseSensitive = caseSensitive; + } + + @Override + public boolean accept(File file) { + String fileName = file.getName(); + String name = this.name; + return caseSensitive ? fileName.equals(name) : fileName.equalsIgnoreCase(name); + } +} diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/filter/TrueFileFilter.java b/microsphere-java-core/src/main/java/io/microsphere/io/filter/TrueFileFilter.java new file mode 100644 index 000000000..b628e8be9 --- /dev/null +++ b/microsphere-java-core/src/main/java/io/microsphere/io/filter/TrueFileFilter.java @@ -0,0 +1,47 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.microsphere.io.filter; + +import java.io.File; + +/** + * {@link IOFileFilter} implementation always returns true + * + * @author Mercy + * @see IOFileFilter + * @since 1.0.0 + */ +public class TrueFileFilter implements IOFileFilter { + + /** + * Singleton instance + */ + public static final TrueFileFilter INSTANCE = new TrueFileFilter(); + + protected TrueFileFilter() { + } + + @Override + public boolean accept(File file) { + return true; + } + + @Override + public boolean accept(File dir, String name) { + return true; + } +} diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/Scanner.java b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/Scanner.java index 293168bc0..000269d18 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/Scanner.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/Scanner.java @@ -12,10 +12,8 @@ /** * {@link Scanner} * - * @param - * the type of scanned source - * @param - * the type of scan result + * @param the type of scanned source + * @param the type of scan result * @author Mercy * @version 1.0.0 * @see Scanner @@ -26,13 +24,10 @@ public interface Scanner { /** * Scan source to calculate result set * - * @param source - * scanned source + * @param source scanned source * @return result set , non-null - * @throws IllegalArgumentException - * scanned source is not legal - * @throws IllegalStateException - * scanned source's state is not valid + * @throws IllegalArgumentException scanned source is not legal + * @throws IllegalStateException scanned source's state is not valid */ @Nonnull Set scan(S source) throws IllegalArgumentException, IllegalStateException; @@ -40,15 +35,11 @@ public interface Scanner { /** * Scan source to calculate result set with {@link Filter} * - * @param source - * scanned source - * @param filter - * {@link Filter filter} to accept result + * @param source scanned source + * @param filter {@link Filter filter} to accept result * @return result set , non-null - * @throws IllegalArgumentException - * scanned source is not legal - * @throws IllegalStateException - * scanned source's state is not valid + * @throws IllegalArgumentException scanned source is not legal + * @throws IllegalStateException scanned source's state is not valid */ @Nonnull Set scan(S source, Filter filter) throws IllegalArgumentException, IllegalStateException; diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleClassScanner.java b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleClassScanner.java index 395e785ef..1f5d4317a 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleClassScanner.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleClassScanner.java @@ -5,16 +5,14 @@ import io.microsphere.filter.FilterUtils; import io.microsphere.filter.PackageNameClassNameFilter; +import io.microsphere.lang.ClassDataRepository; import io.microsphere.util.ClassLoaderUtils; -import io.microsphere.util.ClassUtils; -import org.apache.commons.lang3.StringUtils; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; @@ -23,9 +21,13 @@ import static io.microsphere.lang.function.Streams.filterAll; import static io.microsphere.net.URLUtils.resolveArchiveFile; +import static io.microsphere.util.ClassLoaderUtils.ResourceType.PACKAGE; import static io.microsphere.util.ClassLoaderUtils.findLoadedClass; +import static io.microsphere.util.ClassLoaderUtils.getResources; import static io.microsphere.util.ClassLoaderUtils.loadClass; import static io.microsphere.util.ClassUtils.findClassNamesInClassPath; +import static io.microsphere.util.StringUtils.substringBefore; +import static java.util.Collections.unmodifiableSet; /** * Simple {@link Class} Scanner @@ -90,19 +92,20 @@ public Set> scan(ClassLoader classLoader, String packageName, boolean r public Set> scan(ClassLoader classLoader, String packageName, final boolean recursive, boolean requiredLoad) throws IllegalArgumentException, IllegalStateException { Set> classesSet = new LinkedHashSet(); - final String packageResourceName = ClassLoaderUtils.ResourceType.PACKAGE.resolve(packageName); + final String packageResourceName = PACKAGE.resolve(packageName); try { Set classNames = new LinkedHashSet(); // Find in class loader - Set resourceURLs = ClassLoaderUtils.getResources(classLoader, ClassLoaderUtils.ResourceType.PACKAGE, packageName); + Set resourceURLs = getResources(classLoader, PACKAGE, packageName); if (resourceURLs.isEmpty()) { //Find in class path - List classNamesInPackage = new ArrayList<>(ClassUtils.getClassNamesInPackage(packageName)); + ClassDataRepository repository = ClassDataRepository.INSTANCE; + List classNamesInPackage = new ArrayList<>(repository.getClassNamesInPackage(packageName)); if (!classNamesInPackage.isEmpty()) { - String classPath = ClassUtils.findClassPath(classNamesInPackage.get(0)); + String classPath = repository.findClassPath(classNamesInPackage.get(0)); URL resourceURL = new File(classPath).toURI().toURL(); resourceURLs = new HashSet(); resourceURLs.add(resourceURL); @@ -126,7 +129,7 @@ public Set> scan(ClassLoader classLoader, String packageName, final boo } catch (IOException e) { } - return Collections.unmodifiableSet(classesSet); + return unmodifiableSet(classesSet); } public Set> scan(ClassLoader classLoader, URL resourceInArchive, boolean requiredLoad, @@ -165,7 +168,7 @@ private Set filterClassNames(Set classNames, String packageName, private URL resolveClassPathURL(URL resourceURL, String packageResourceName) { String resource = resourceURL.toExternalForm(); - String classPath = StringUtils.substringBefore(resource, packageResourceName); + String classPath = substringBefore(resource, packageResourceName); URL classPathURL = null; try { classPathURL = new URL(classPath); diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java index 4756b18d2..b95b967b6 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java @@ -1,14 +1,16 @@ package io.microsphere.io.scanner; -import org.apache.commons.io.filefilter.IOFileFilter; -import org.apache.commons.io.filefilter.TrueFileFilter; + +import io.microsphere.io.filter.IOFileFilter; +import io.microsphere.io.filter.TrueFileFilter; import javax.annotation.Nonnull; import java.io.File; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.Set; +import static java.util.Collections.unmodifiableSet; + /** * Simple File Scanner (Single-Thread) * @@ -72,7 +74,7 @@ public Set scan(File rootDirectory, boolean recursive, IOFileFilter ioFile } } } - return Collections.unmodifiableSet(filesSet); + return unmodifiableSet(filesSet); } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleJarEntryScanner.java b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleJarEntryScanner.java index 177789f63..9694f3e3b 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleJarEntryScanner.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleJarEntryScanner.java @@ -6,18 +6,19 @@ import io.microsphere.constants.PathConstants; import io.microsphere.filter.JarEntryFilter; import io.microsphere.util.jar.JarUtils; -import org.apache.commons.lang3.StringUtils; import javax.annotation.Nonnull; import java.io.IOException; import java.net.URL; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; +import static io.microsphere.util.StringUtils.EMPTY; +import static java.util.Collections.unmodifiableSet; + /** * Simple {@link JarEntry} Scanner * @@ -36,17 +37,12 @@ public SimpleJarEntryScanner() { } /** - * @param jarURL - * {@link URL} of {@link JarFile} or {@link JarEntry} - * @param recursive - * recursive + * @param jarURL {@link URL} of {@link JarFile} or {@link JarEntry} + * @param recursive recursive * @return Read-only {@link Set} - * @throws NullPointerException - * If argument null - * @throws IllegalArgumentException - *