elements
* @return read-only {@link Set}
*/
- public static elements
* @return read-only {@link Set}
*/
- public static + * 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
+ * The difference between File.delete() and this method are:
+ * 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 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 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
+ * Equivalent to {@link Closeable#close()}, except any exceptions will be ignored.
+ * This is typically used in finally blocks.
+ *
+ * Example code:
+ * This form avoids superfluous string concatenation when the logger
+ * is disabled for the TRACE level. However, this variant incurs the hidden
+ * (and relatively small) cost of creating an 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.
+ *
+ *
+ *
+ * @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.
+ * 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}.
+ * 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.
+ * Closeable
.
+ *
+ * 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 scanned source
+ * @param {
/**
* 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 source to calculate result set with {@link Filter}
*
- * @param source
- * scanned source
- * @param filter
- * {@link Filternull
- * @throws IllegalArgumentException
- *
null
+ * @throws IllegalArgumentException
null
- * @throws IllegalArgumentException
- * {@link JarUtils#resolveJarAbsolutePath(URL)}
- * @throws IOException
- * {@link JarUtils#toJarFile(URL)}
+ * @throws NullPointerException If argument null
+ * @throws IllegalArgumentException {@link JarUtils#resolveJarAbsolutePath(URL)}
+ * @throws IOException {@link JarUtils#toJarFile(URL)}
* @see JarEntryFilter
* @since 1.0.0
*/
@@ -101,7 +91,7 @@ public Setnull
.
+ * @throws NullPointerException If type
is null
, {@link NullPointerException} will be thrown.
+ */
+ public URL getCodeSourceLocation(Class> type) throws NullPointerException {
+
+ URL codeSourceLocation = null;
+ ClassLoader classLoader = type.getClassLoader();
+
+ if (classLoader == null) { // Bootstrap ClassLoader or type is primitive or void
+ String path = findClassPath(type);
+ if (isNotBlank(path)) {
+ try {
+ codeSourceLocation = new File(path).toURI().toURL();
+ } catch (MalformedURLException ignored) {
+ codeSourceLocation = null;
+ }
+ }
+ } else {
+ ProtectionDomain protectionDomain = type.getProtectionDomain();
+ CodeSource codeSource = protectionDomain == null ? null : protectionDomain.getCodeSource();
+ codeSourceLocation = codeSource == null ? null : codeSource.getLocation();
+ }
+ return codeSourceLocation;
+ }
+
+ private Mapfunction
is null
+ */
+ static function
and exceptionHandler
is null
+ */
+ static Logger
instance.
+ *
+ * @return name of this logger instance
+ */
+ String getName();
+
+ /**
+ * Is the logger instance enabled for the TRACE level?
+ *
+ * @return True if this Logger is enabled for the TRACE level,
+ * false otherwise.
+ */
+ boolean isTraceEnabled();
+
+ /**
+ * Log a message at the TRACE level.
+ *
+ * @param message the message string to be logged
+ */
+ void trace(String message);
+
+ /**
+ * Log a message at the TRACE level according to the specified format
+ * and arguments.
+ *
+ * Object[]
before invoking the method,
+ * even if this logger is disabled for TRACE.
+ *
+ * @param format the format string
+ * @param arguments the arguments
+ */
+ void trace(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the TRACE level with an
+ * accompanying message.
+ *
+ * @param message the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ void trace(String message, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the DEBUG level?
+ *
+ * @return True if this Logger is enabled for the DEBUG level,
+ * false otherwise.
+ */
+ boolean isDebugEnabled();
+
+ /**
+ * Log a message at the DEBUG level.
+ *
+ * @param message the message string to be logged
+ */
+ void debug(String message);
+
+ /**
+ * Log a message at the DEBUG level according to the specified format
+ * and arguments.
+ *
+ * @param format the format string
+ * @param arguments the arguments
+ */
+ void debug(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the DEBUG level with an
+ * accompanying message.
+ *
+ * @param message the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ void debug(String message, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the INFO level?
+ *
+ * @return True if this Logger is enabled for the INFO level,
+ * false otherwise.
+ */
+ boolean isInfoEnabled();
+
+ /**
+ * Log a message at the INFO level.
+ *
+ * @param message the message string to be logged
+ */
+ void info(String message);
+
+ /**
+ * Log a message at the INFO level according to the specified format
+ * and arguments.
+ *
+ * @param format the format string
+ * @param arguments the arguments
+ */
+ void info(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the INFO level with an
+ * accompanying message.
+ *
+ * @param message the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ void info(String message, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the WARN level?
+ *
+ * @return True if this Logger is enabled for the WARN level,
+ * false otherwise.
+ */
+ boolean isWarnEnabled();
+
+ /**
+ * Log a message at the WARN level.
+ *
+ * @param message the message string to be logged
+ */
+ void warn(String message);
+
+ /**
+ * Log a message at the WARN level according to the specified format
+ * and arguments.
+ *
+ * @param format the format string
+ * @param arguments the arguments
+ */
+ void warn(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the WARN level with an
+ * accompanying message.
+ *
+ * @param message the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ void warn(String message, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the ERROR level?
+ *
+ * @return True if this Logger is enabled for the ERROR level,
+ * false otherwise.
+ */
+ boolean isErrorEnabled();
+
+ /**
+ * Log a message at the ERROR level.
+ *
+ * @param message the message string to be logged
+ */
+ void error(String message);
+
+ /**
+ * Log a message at the ERROR level according to the specified format
+ * and arguments.
+ *
+ * @param format the format string
+ * @param arguments the arguments
+ */
+ void error(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the ERROR level with an
+ * accompanying message.
+ *
+ * @param message the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ void error(String message, Throwable t);
+
+}
diff --git a/microsphere-java-core/src/main/java/io/microsphere/logging/LoggerFactory.java b/microsphere-java-core/src/main/java/io/microsphere/logging/LoggerFactory.java
new file mode 100644
index 000000000..51f445d6c
--- /dev/null
+++ b/microsphere-java-core/src/main/java/io/microsphere/logging/LoggerFactory.java
@@ -0,0 +1,125 @@
+/*
+ * 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.logging;
+
+import io.microsphere.lang.Prioritized;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.List;
+
+import static io.microsphere.collection.ListUtils.newLinkedList;
+import static java.util.Collections.sort;
+import static java.util.ServiceLoader.load;
+
+/**
+ * The factory class for {@link Logger}
+ *
+ * @author Mercy
+ * @see Logger
+ * @since 1.0.0
+ */
+public abstract class LoggerFactory {
+
+ private static final ClassLoader classLoader = LoggerFactory.class.getClassLoader();
+
+ @Nullable
+ private static final LoggerFactory factory = loadFactory();
+
+ @Nullable
+ private static LoggerFactory loadFactory() {
+ Listtrue
if available
+ */
+ protected boolean isAvailable() {
+ return getDelegateLoggerClass() != null;
+ }
+
+ /**
+ * The class of delegate Logger
+ *
+ * @return null
if not found
+ */
+ private Class> getDelegateLoggerClass() {
+ String className = getDelegateLoggerClassName();
+ Class> delegateLoggerClass = null;
+ try {
+ delegateLoggerClass = classLoader.loadClass(className);
+ } catch (Throwable e) {
+ }
+ return delegateLoggerClass;
+ }
+
+ /**
+ * The class name of delegate Logger
+ *
+ * @return non-null
+ */
+ protected abstract String getDelegateLoggerClassName();
+
+ /**
+ * Create a new {@link Logger}
+ *
+ * @param name the name of {@link Logger }
+ * @return non-null
+ */
+ public abstract Logger createLogger(String name);
+
+}
diff --git a/microsphere-java-core/src/main/java/io/microsphere/logging/NoOpLogger.java b/microsphere-java-core/src/main/java/io/microsphere/logging/NoOpLogger.java
new file mode 100644
index 000000000..33268a1c4
--- /dev/null
+++ b/microsphere-java-core/src/main/java/io/microsphere/logging/NoOpLogger.java
@@ -0,0 +1,116 @@
+/*
+ * 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.logging;
+
+/**
+ * No-Operation {@link Logger}
+ *
+ * @author Mercy
+ * @see Logger
+ * @since 1.0.0
+ */
+final class NoOpLogger extends AbstractLogger {
+
+ NoOpLogger(String name) {
+ super(name);
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return false;
+ }
+
+ @Override
+ public void trace(String message) {
+ }
+
+ @Override
+ public void trace(String format, Object... arguments) {
+ }
+
+ @Override
+ public void trace(String message, Throwable t) {
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return false;
+ }
+
+ @Override
+ public void debug(String message) {
+ }
+
+ @Override
+ public void debug(String format, Object... arguments) {
+ }
+
+ @Override
+ public void debug(String message, Throwable t) {
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return false;
+ }
+
+ @Override
+ public void info(String message) {
+ }
+
+ @Override
+ public void info(String format, Object... arguments) {
+ }
+
+ @Override
+ public void info(String message, Throwable t) {
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return false;
+ }
+
+ @Override
+ public void warn(String message) {
+ }
+
+ @Override
+ public void warn(String format, Object... arguments) {
+ }
+
+ @Override
+ public void warn(String message, Throwable t) {
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return false;
+ }
+
+ @Override
+ public void error(String message) {
+ }
+
+ @Override
+ public void error(String format, Object... arguments) {
+ }
+
+ @Override
+ public void error(String message, Throwable t) {
+ }
+}
\ No newline at end of file
diff --git a/microsphere-java-core/src/main/java/io/microsphere/logging/Sfl4jLoggerFactory.java b/microsphere-java-core/src/main/java/io/microsphere/logging/Sfl4jLoggerFactory.java
new file mode 100644
index 000000000..e1a7ec220
--- /dev/null
+++ b/microsphere-java-core/src/main/java/io/microsphere/logging/Sfl4jLoggerFactory.java
@@ -0,0 +1,157 @@
+/*
+ * 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.logging;
+
+import io.microsphere.lang.Prioritized;
+
+/**
+ * The {@link LoggerFactory} class for Slf4j
+ *
+ * @author Mercy
+ * @see LoggerFactory
+ * @since 1.0.0
+ */
+public class Sfl4jLoggerFactory extends LoggerFactory implements Prioritized {
+
+ public static final String SLF4J_LOGGER_CLASS_NAME = "org.slf4j.Logger";
+
+ @Override
+ protected String getDelegateLoggerClassName() {
+ return SLF4J_LOGGER_CLASS_NAME;
+ }
+
+ @Override
+ public Logger createLogger(String name) {
+ return new Sfl4jLogger(name);
+ }
+
+ @Override
+ public int getPriority() {
+ return NORMAL_PRIORITY;
+ }
+
+ static class Sfl4jLogger extends AbstractLogger {
+
+ private final org.slf4j.Logger logger;
+
+ protected Sfl4jLogger(String name) {
+ super(name);
+ this.logger = org.slf4j.LoggerFactory.getLogger(name);
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return logger.isTraceEnabled();
+ }
+
+ @Override
+ public void trace(String message) {
+ logger.trace(message);
+ }
+
+ @Override
+ public void trace(String format, Object... arguments) {
+ logger.trace(format, arguments);
+ }
+
+ @Override
+ public void trace(String message, Throwable t) {
+ logger.trace(message, t);
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return logger.isDebugEnabled();
+ }
+
+ @Override
+ public void debug(String message) {
+ logger.debug(message);
+ }
+
+ @Override
+ public void debug(String format, Object... arguments) {
+ logger.debug(format, arguments);
+ }
+
+ @Override
+ public void debug(String message, Throwable t) {
+ logger.debug(message, t);
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return logger.isInfoEnabled();
+ }
+
+ @Override
+ public void info(String message) {
+ logger.info(message);
+ }
+
+ @Override
+ public void info(String format, Object... arguments) {
+ logger.info(format, arguments);
+ }
+
+ @Override
+ public void info(String message, Throwable t) {
+ logger.info(message, t);
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return logger.isWarnEnabled();
+ }
+
+ @Override
+ public void warn(String message) {
+ logger.warn(message);
+ }
+
+ @Override
+ public void warn(String format, Object... arguments) {
+ logger.warn(format, arguments);
+ }
+
+ @Override
+ public void warn(String message, Throwable t) {
+ logger.warn(message, t);
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return logger.isErrorEnabled();
+ }
+
+ @Override
+ public void error(String message) {
+ logger.error(message);
+ }
+
+ @Override
+ public void error(String format, Object... arguments) {
+ logger.error(format, arguments);
+ }
+
+ @Override
+ public void error(String message, Throwable t) {
+ logger.error(message, t);
+ }
+
+ }
+}
diff --git a/microsphere-java-core/src/main/java/io/microsphere/management/JmxUtils.java b/microsphere-java-core/src/main/java/io/microsphere/management/JmxUtils.java
index 4054753cb..f765cda18 100644
--- a/microsphere-java-core/src/main/java/io/microsphere/management/JmxUtils.java
+++ b/microsphere-java-core/src/main/java/io/microsphere/management/JmxUtils.java
@@ -16,9 +16,8 @@
*/
package io.microsphere.management;
+import io.microsphere.logging.Logger;
import io.microsphere.util.BaseUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -35,6 +34,7 @@
import java.util.Objects;
import static io.microsphere.collection.MapUtils.newHashMap;
+import static io.microsphere.logging.LoggerFactory.getLogger;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableMap;
@@ -47,7 +47,7 @@
*/
public abstract class JmxUtils extends BaseUtils {
- private static final Logger logger = LoggerFactory.getLogger(JmxUtils.class);
+ private static final Logger logger = getLogger(JmxUtils.class);
private static final MBeanAttribute[] EMPTY_MBEAN_ATTRIBUTE_ARRAY = new MBeanAttribute[0];
diff --git a/microsphere-java-core/src/main/java/io/microsphere/management/ManagementUtils.java b/microsphere-java-core/src/main/java/io/microsphere/management/ManagementUtils.java
index 9a6040273..788c5ced4 100644
--- a/microsphere-java-core/src/main/java/io/microsphere/management/ManagementUtils.java
+++ b/microsphere-java-core/src/main/java/io/microsphere/management/ManagementUtils.java
@@ -1,13 +1,16 @@
package io.microsphere.management;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.lang3.math.NumberUtils;
-import java.lang.management.ManagementFactory;
+import io.microsphere.logging.Logger;
+
import java.lang.management.RuntimeMXBean;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Arrays;
+
+import static io.microsphere.logging.LoggerFactory.getLogger;
+import static io.microsphere.reflect.FieldUtils.getFieldValue;
+import static io.microsphere.reflect.MethodUtils.invokeMethod;
+import static io.microsphere.util.StringUtils.substringBefore;
+import static java.lang.Integer.parseInt;
+import static java.lang.management.ManagementFactory.getRuntimeMXBean;
/**
* Management Utility class
@@ -19,10 +22,12 @@
*/
public abstract class ManagementUtils {
+ private static final Logger logger = getLogger(ManagementUtils.class);
+
/**
* {@link RuntimeMXBean}
*/
- private final static RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
+ private final static RuntimeMXBean runtimeMXBean = getRuntimeMXBean();
/**
* "jvm" Field name
@@ -34,57 +39,23 @@ public abstract class ManagementUtils {
final static Object jvm = initJvm();
/**
* "getProcessId" Method name
+ *
+ * @see sun.management.VMManagementImpl#getProcessId()
*/
private final static String GET_PROCESS_ID_METHOD_NAME = "getProcessId";
- /**
- * "getProcessId" Method
- */
- final static Method getProcessIdMethod = initGetProcessIdMethod();
-
private static Object initJvm() {
Object jvm = null;
- Field jvmField = null;
if (runtimeMXBean != null) {
try {
- jvmField = runtimeMXBean.getClass().getDeclaredField(JVM_FIELD_NAME);
- jvmField.setAccessible(true);
- jvm = jvmField.get(runtimeMXBean);
- } catch (Exception ignored) {
- System.err.printf("The Field[name : %s] can't be found in RuntimeMXBean Class[%s]!\n", JVM_FIELD_NAME, runtimeMXBean.getClass());
+ jvm = getFieldValue(runtimeMXBean, JVM_FIELD_NAME);
+ } catch (Throwable e) {
+ logger.error("The Field[name : '{}'] can't be found in RuntimeMXBean class : '{}'!", JVM_FIELD_NAME, runtimeMXBean.getClass(), e);
}
}
return jvm;
}
- private static Method initGetProcessIdMethod() {
- Class> jvmClass = jvm.getClass();
-
- Method getProcessIdMethod = null;
- try {
- getProcessIdMethod = jvmClass.getDeclaredMethod(GET_PROCESS_ID_METHOD_NAME);
- getProcessIdMethod.setAccessible(true);
- } catch (Exception ignored) {
- System.err.printf("%s method can't be found in class[%s]!\n", GET_PROCESS_ID_METHOD_NAME, jvmClass.getName());
- }
- return getProcessIdMethod;
- }
-
- private static Object invoke(Method method, Object object, Object... arguments) {
- Object result = null;
- try {
- if (!method.isAccessible()) {
- method.setAccessible(true);
- }
- result = method.invoke(object, arguments);
- } catch (Exception ignored) {
- System.err.printf("%s method[arguments : %s] can't be invoked in object[%s]!\n",
- method.getName(), Arrays.asList(arguments), object);
- }
-
- return result;
- }
-
/**
* Get the process ID of current JVM
*
@@ -92,16 +63,21 @@ private static Object invoke(Method method, Object object, Object... arguments)
*/
public static int getCurrentProcessId() {
int processId = -1;
- Object result = invoke(getProcessIdMethod, jvm);
+ Object result = null;
+
+ try {
+ result = invokeMethod(jvm, GET_PROCESS_ID_METHOD_NAME);
+ } catch (Throwable e) {
+ logger.error("The method 'sun.management.VMManagementImpl#getProcessId()' can't be invoked!", e);
+ }
+
if (result instanceof Integer) {
processId = (Integer) result;
} else {
// no guarantee
String name = runtimeMXBean.getName();
- String processIdValue = StringUtils.substringBefore(name, "@");
- if (NumberUtils.isNumber(processIdValue)) {
- processId = Integer.parseInt(processIdValue);
- }
+ String processIdValue = substringBefore(name, "@");
+ processId = parseInt(processIdValue);
}
return processId;
}
diff --git a/microsphere-java-core/src/main/java/io/microsphere/misc/UnsafeUtils.java b/microsphere-java-core/src/main/java/io/microsphere/misc/UnsafeUtils.java
index a4d0ea116..d3514fe43 100644
--- a/microsphere-java-core/src/main/java/io/microsphere/misc/UnsafeUtils.java
+++ b/microsphere-java-core/src/main/java/io/microsphere/misc/UnsafeUtils.java
@@ -1,1175 +1,1175 @@
-package io.microsphere.misc;
-
-import io.microsphere.reflect.ReflectionUtils;
-import org.apache.commons.lang3.reflect.FieldUtils;
-import sun.misc.Unsafe;
-
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedExceptionAction;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-import static io.microsphere.reflect.ReflectionUtils.assertArrayIndex;
-import static io.microsphere.reflect.ReflectionUtils.assertFieldMatchType;
-
-/**
- * {@link Unsafe} Utility class Take case to use those utility methods in order to the stability fo
- * JVM
- *
- * @author Mercy
- * @version 1.0.0
- * @see UnsafeUtils
- * @since 1.0.0
- */
-public abstract class UnsafeUtils {
-
- final static Unsafe unsafe;
-
- /**
- * long
Array base index
- */
- static final int LONG_ARRAY_BASE_OFFSET;
-
- /**
- * int
Array base index
- */
- static final int INT_ARRAY_BASE_OFFSET;
-
- /**
- * short
Array base index
- */
- static final int SHORT_ARRAY_BASE_OFFSET;
-
- /**
- * byte
Array base index
- */
- static final int BYTE_ARRAY_BASE_OFFSET;
-
- /**
- * boolean
Array base index
- */
- static final int BOOLEAN_ARRAY_BASE_OFFSET;
-
- /**
- * double
Array base index
- */
- static final int DOUBLE_ARRAY_BASE_OFFSET;
-
- /**
- * float
Array base index
- */
- static final int FLOAT_ARRAY_BASE_OFFSET;
-
- /**
- * char
Array base index
- */
- static final int CHAR_ARRAY_BASE_OFFSET;
-
- /**
- * java.lang.Object
Array base index
- */
- static final int OBJECT_ARRAY_BASE_OFFSET;
-
- /**
- * long
Array Index scale
- */
- static final int LONG_ARRAY_INDEX_SCALE;
-
- /**
- * int
Array Index scale
- */
- static final int INT_ARRAY_INDEX_SCALE;
-
- /**
- * short
Array Index scale
- */
- static final int SHORT_ARRAY_INDEX_SCALE;
-
- /**
- * byte
Array Index scale
- */
- static final int BYTE_ARRAY_INDEX_SCALE;
-
- /**
- * boolean
Array Index scale
- */
- static final int BOOLEAN_ARRAY_INDEX_SCALE;
-
- /**
- * double
Array Index scale
- */
- static final int DOUBLE_ARRAY_INDEX_SCALE;
-
- /**
- * float
Array Index scale
- */
- static final int FLOAT_ARRAY_INDEX_SCALE;
-
- /**
- * char
Array Index scale
- */
- static final int CHAR_ARRAY_INDEX_SCALE;
-
- /**
- * java.lang.Object
Array Index scale
- */
- static final int OBJECT_ARRAY_INDEX_SCALE;
-
- /**
- * Offset Cache,
- */
- private final static ConcurrentMaplong
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long longArrayIndexOffset(int index) {
- return arrayIndexOffset(index, LONG_ARRAY_BASE_OFFSET, LONG_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate
int
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long intArrayIndexOffset(int index) {
- return arrayIndexOffset(index, INT_ARRAY_BASE_OFFSET, INT_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate the
short
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long shortArrayIndexOffset(int index) {
- return arrayIndexOffset(index, SHORT_ARRAY_BASE_OFFSET, SHORT_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate the relative offset of Array Index of type
byte
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long byteArrayIndexOffset(int index) {
- return arrayIndexOffset(index, BYTE_ARRAY_BASE_OFFSET, BYTE_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate
boolean
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long booleanArrayIndexOffset(int index) {
- return arrayIndexOffset(index, BOOLEAN_ARRAY_BASE_OFFSET, BOOLEAN_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate the relative offset of Array Index of type
double
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long doubleArrayIndexOffset(int index) {
- return arrayIndexOffset(index, DOUBLE_ARRAY_BASE_OFFSET, DOUBLE_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate
float
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long floatArrayIndexOffset(int index) {
- return arrayIndexOffset(index, FLOAT_ARRAY_BASE_OFFSET, FLOAT_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate
char
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long charArrayIndexOffset(int index) {
- return arrayIndexOffset(index, CHAR_ARRAY_BASE_OFFSET, CHAR_ARRAY_INDEX_SCALE);
- }
-
- /**
- * Calculate
java.lang.Object
type Array Index the relative offset
- *
- * @param index Array Index
- * @return the relative offset
- */
- protected static long objectArrayIndexOffset(int index) {
- return arrayIndexOffset(index, OBJECT_ARRAY_BASE_OFFSET, OBJECT_ARRAY_INDEX_SCALE);
- }
-
-
- /**
- * Create Offset Cache Key
- *
- * @param type the target type
- * @param fieldName the name of {@link Field}
- * @return The cache key of offset
- */
- protected static String createOffsetCacheKey(Class> type, String fieldName) {
- StringBuilder keyBuilder = new StringBuilder(type.getName()).append("#").append(fieldName);
- return keyBuilder.toString();
- }
-
- /**
- * Get Offset in cache
- *
- * @param type the target type
- * @param fieldName the name of {@link Field}
- * @return Offset
- */
- protected static Long getOffsetFromCache(Class> type, String fieldName) {
- String key = createOffsetCacheKey(type, fieldName);
- return offsetCache.get(key);
- }
-
- /**
- * Save offset to cache
- *
- * @param type the target type
- * @param fieldName the name of {@link Field}
- * @param offset offset
- */
- protected static void putOffsetFromCache(Class> type, String fieldName, long offset) {
- String key = createOffsetCacheKey(type, fieldName);
- offsetCache.putIfAbsent(key, offset);
- }
-
-
- /**
- * Get the
long
value of the target Index in the Array field of the object
- *
- * @param object Object
- * @param fieldName the name of {@link Field}
- * @param index the index
- * @return the
long
value
- */
- public static long getLongFromArrayVolatile(Object object, String fieldName, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException, IllegalAccessException {
- Object array = FieldUtils.readDeclaredField(object, fieldName, true);
- long offset = longArrayIndexOffset(index);
- return unsafe.getLongVolatile(array, offset);
- }
-
- /**
- * Get the value of the target Index in the object Array field
- *
- * @param object Object
- * @param fieldName the name of {@link Field}
- * @param index the index
- * @return the
int
value
- */
- public static int getIntFromArrayVolatile(Object object, String fieldName, int index) throws IllegalArgumentException, ArrayIndexOutOfBoundsException, IllegalAccessException {
- Object array = FieldUtils.readDeclaredField(object, fieldName, true);
- assertArrayIndex(array, index);
- long offset = intArrayIndexOffset(index);
- return unsafe.getIntVolatile(array, offset);
- }
-
- /**
- * Get the