1. 首次提交

This commit is contained in:
刘福顺 2024-05-20 17:43:59 +08:00
commit 24b498dbd0
28 changed files with 2112 additions and 0 deletions

33
.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

BIN
.mvn/wrapper/maven-wrapper.jar vendored Normal file

Binary file not shown.

2
.mvn/wrapper/maven-wrapper.properties vendored Normal file
View File

@ -0,0 +1,2 @@
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.5/apache-maven-3.9.5-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar

23
jniconfig.json Normal file
View File

@ -0,0 +1,23 @@
[
{
"name" : "com.cInterface.Data",
"queryAllDeclaredConstructors" : true,
"queryAllPublicConstructors" : true,
"queryAllDeclaredMethods" : true,
"queryAllPublicMethods" : true,
"allDeclaredClasses" : true,
"allPublicClasses" : true
},
{
"name" : "com.cInterface.Data",
"fields" : [
{ "name" : "mParam" },
{ "name" : "mInfo" }
],
"methods" : [
{ "name" : "<init>", "parameterTypes" : [] },
{ "name" : "getParam", "parameterTypes" : [] },
{ "name" : "setInfo", "parameterTypes" : ["byte[]", "int"] }
]
}
]

308
mvnw vendored Normal file
View File

@ -0,0 +1,308 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# 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
#
# https://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.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.2.0
#
# Required ENV vars:
# ------------------
# JAVA_HOME - location of a JDK home dir
#
# Optional ENV vars
# -----------------
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
# e.g. to debug Maven itself, use
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
# ----------------------------------------------------------------------------
if [ -z "$MAVEN_SKIP_RC" ] ; then
if [ -f /usr/local/etc/mavenrc ] ; then
. /usr/local/etc/mavenrc
fi
if [ -f /etc/mavenrc ] ; then
. /etc/mavenrc
fi
if [ -f "$HOME/.mavenrc" ] ; then
. "$HOME/.mavenrc"
fi
fi
# OS specific support. $var _must_ be set to either true or false.
cygwin=false;
darwin=false;
mingw=false
case "$(uname)" in
CYGWIN*) cygwin=true ;;
MINGW*) mingw=true;;
Darwin*) darwin=true
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
if [ -z "$JAVA_HOME" ]; then
if [ -x "/usr/libexec/java_home" ]; then
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
else
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
fi
fi
;;
esac
if [ -z "$JAVA_HOME" ] ; then
if [ -r /etc/gentoo-release ] ; then
JAVA_HOME=$(java-config --jre-home)
fi
fi
# For Cygwin, ensure paths are in UNIX format before anything is touched
if $cygwin ; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
fi
# For Mingw, ensure paths are in UNIX format before anything is touched
if $mingw ; then
[ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
fi
if [ -z "$JAVA_HOME" ]; then
javaExecutable="$(which javac)"
if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
# readlink(1) is not available as standard on Solaris 10.
readLink=$(which readlink)
if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
if $darwin ; then
javaHome="$(dirname "\"$javaExecutable\"")"
javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
else
javaExecutable="$(readlink -f "\"$javaExecutable\"")"
fi
javaHome="$(dirname "\"$javaExecutable\"")"
javaHome=$(expr "$javaHome" : '\(.*\)/bin')
JAVA_HOME="$javaHome"
export JAVA_HOME
fi
fi
fi
if [ -z "$JAVACMD" ] ; then
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
else
JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
fi
fi
if [ ! -x "$JAVACMD" ] ; then
echo "Error: JAVA_HOME is not defined correctly." >&2
echo " We cannot execute $JAVACMD" >&2
exit 1
fi
if [ -z "$JAVA_HOME" ] ; then
echo "Warning: JAVA_HOME environment variable is not set."
fi
# traverses directory structure from process work directory to filesystem root
# first directory with .mvn subdirectory is considered project base directory
find_maven_basedir() {
if [ -z "$1" ]
then
echo "Path not specified to find_maven_basedir"
return 1
fi
basedir="$1"
wdir="$1"
while [ "$wdir" != '/' ] ; do
if [ -d "$wdir"/.mvn ] ; then
basedir=$wdir
break
fi
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
if [ -d "${wdir}" ]; then
wdir=$(cd "$wdir/.." || exit 1; pwd)
fi
# end of workaround
done
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
}
# concatenates all lines of a file
concat_lines() {
if [ -f "$1" ]; then
# Remove \r in case we run on Windows within Git Bash
# and check out the repository with auto CRLF management
# enabled. Otherwise, we may read lines that are delimited with
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
# splitting rules.
tr -s '\r\n' ' ' < "$1"
fi
}
log() {
if [ "$MVNW_VERBOSE" = true ]; then
printf '%s\n' "$1"
fi
}
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
if [ -z "$BASE_DIR" ]; then
exit 1;
fi
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
log "$MAVEN_PROJECTBASEDIR"
##########################################################################################
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
# This allows using the maven wrapper in projects that prohibit checking in binary data.
##########################################################################################
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
if [ -r "$wrapperJarPath" ]; then
log "Found $wrapperJarPath"
else
log "Couldn't find $wrapperJarPath, downloading it ..."
if [ -n "$MVNW_REPOURL" ]; then
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
else
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
fi
while IFS="=" read -r key value; do
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
safeValue=$(echo "$value" | tr -d '\r')
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
log "Downloading from: $wrapperUrl"
if $cygwin; then
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
fi
if command -v wget > /dev/null; then
log "Found wget ... using wget"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
else
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
fi
elif command -v curl > /dev/null; then
log "Found curl ... using curl"
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
else
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
fi
else
log "Falling back to using Java to download"
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
# For Cygwin, switch paths to Windows format before running javac
if $cygwin; then
javaSource=$(cygpath --path --windows "$javaSource")
javaClass=$(cygpath --path --windows "$javaClass")
fi
if [ -e "$javaSource" ]; then
if [ ! -e "$javaClass" ]; then
log " - Compiling MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/javac" "$javaSource")
fi
if [ -e "$javaClass" ]; then
log " - Running MavenWrapperDownloader.java ..."
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
fi
fi
fi
fi
##########################################################################################
# End of extension
##########################################################################################
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
wrapperSha256Sum=""
while IFS="=" read -r key value; do
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
esac
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
if [ -n "$wrapperSha256Sum" ]; then
wrapperSha256Result=false
if command -v sha256sum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
elif command -v shasum > /dev/null; then
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
wrapperSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
exit 1
fi
if [ $wrapperSha256Result = false ]; then
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
exit 1
fi
fi
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
# For Cygwin, switch paths to Windows format before running java
if $cygwin; then
[ -n "$JAVA_HOME" ] &&
JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
[ -n "$CLASSPATH" ] &&
CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
fi
# Provide a "standardized" way to retrieve the CLI args that will
# work with both Windows and non-Windows executions.
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
export MAVEN_CMD_LINE_ARGS
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
# shellcheck disable=SC2086 # safe args
exec "$JAVACMD" \
$MAVEN_OPTS \
$MAVEN_DEBUG_OPTS \
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

205
mvnw.cmd vendored Normal file
View File

@ -0,0 +1,205 @@
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM https://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.2.0
@REM
@REM Required ENV vars:
@REM JAVA_HOME - location of a JDK home dir
@REM
@REM Optional ENV vars
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
@REM e.g. to debug Maven itself, use
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
@REM ----------------------------------------------------------------------------
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
@echo off
@REM set title of command window
title %0
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
@REM set %HOME% to equivalent of $HOME
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
@REM Execute a user defined script before this one
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
:skipRcPre
@setlocal
set ERROR_CODE=0
@REM To isolate internal variables from possible post scripts, we use another setlocal
@setlocal
@REM ==== START VALIDATION ====
if not "%JAVA_HOME%" == "" goto OkJHome
echo.
echo Error: JAVA_HOME not found in your environment. >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
:OkJHome
if exist "%JAVA_HOME%\bin\java.exe" goto init
echo.
echo Error: JAVA_HOME is set to an invalid directory. >&2
echo JAVA_HOME = "%JAVA_HOME%" >&2
echo Please set the JAVA_HOME variable in your environment to match the >&2
echo location of your Java installation. >&2
echo.
goto error
@REM ==== END VALIDATION ====
:init
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
@REM Fallback to current working directory if not found.
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
set EXEC_DIR=%CD%
set WDIR=%EXEC_DIR%
:findBaseDir
IF EXIST "%WDIR%"\.mvn goto baseDirFound
cd ..
IF "%WDIR%"=="%CD%" goto baseDirNotFound
set WDIR=%CD%
goto findBaseDir
:baseDirFound
set MAVEN_PROJECTBASEDIR=%WDIR%
cd "%EXEC_DIR%"
goto endDetectBaseDir
:baseDirNotFound
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
cd "%EXEC_DIR%"
:endDetectBaseDir
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
@setlocal EnableExtensions EnableDelayedExpansion
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
:endReadAdditionalConfig
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
set WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperUrl" SET WRAPPER_URL=%%B
)
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
if exist %WRAPPER_JAR% (
if "%MVNW_VERBOSE%" == "true" (
echo Found %WRAPPER_JAR%
)
) else (
if not "%MVNW_REPOURL%" == "" (
SET WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
)
if "%MVNW_VERBOSE%" == "true" (
echo Couldn't find %WRAPPER_JAR%, downloading it ...
echo Downloading from: %WRAPPER_URL%
)
powershell -Command "&{"^
"$webclient = new-object System.Net.WebClient;"^
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
"}"^
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
"}"
if "%MVNW_VERBOSE%" == "true" (
echo Finished downloading %WRAPPER_JAR%
)
)
@REM End of extension
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
SET WRAPPER_SHA_256_SUM=""
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
)
IF NOT %WRAPPER_SHA_256_SUM%=="" (
powershell -Command "&{"^
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
" exit 1;"^
"}"^
"}"
if ERRORLEVEL 1 goto error
)
@REM Provide a "standardized" way to retrieve the CLI args that will
@REM work with both Windows and non-Windows executions.
set MAVEN_CMD_LINE_ARGS=%*
%MAVEN_JAVA_EXE% ^
%JVM_CONFIG_MAVEN_PROPS% ^
%MAVEN_OPTS% ^
%MAVEN_DEBUG_OPTS% ^
-classpath %WRAPPER_JAR% ^
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
if ERRORLEVEL 1 goto error
goto end
:error
set ERROR_CODE=1
:end
@endlocal & set ERROR_CODE=%ERROR_CODE%
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
@REM check for post script, once with legacy .bat ending and once with .cmd ending
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
:skipRcPost
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
if "%MAVEN_BATCH_PAUSE%"=="on" pause
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
cmd /C exit /B %ERROR_CODE%

147
pom.xml Normal file
View File

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- <parent>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-parent</artifactId>-->
<!-- <version>3.2.2</version>-->
<!-- <relativePath/> &lt;!&ndash; lookup parent from repository &ndash;&gt;-->
<!-- </parent>-->
<groupId>org.aohe</groupId>
<artifactId>scan-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>scan-service</name>
<description>scan-service</description>
<properties>
<java.version>8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.5.3</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
</dependency>
<dependency>
<groupId>com.googlecode.jfreesane</groupId>
<artifactId>jfreesane</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.45</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>org.aohe</groupId>
<artifactId>twain-service</artifactId>
<version>0.1.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- <plugin>-->
<!-- <groupId>org.graalvm.buildtools</groupId>-->
<!-- <artifactId>native-maven-plugin</artifactId>-->
<!-- </plugin>-->
<!-- <plugin>-->
<!-- <groupId>org.apache.maven.plugins</groupId>-->
<!-- <artifactId>maven-assembly-plugin</artifactId>-->
<!-- <version>2.3</version>-->
<!-- <configuration>-->
<!-- &lt;!&ndash;如果不想在打包的后缀加上 assembly.xml 中设置的 id可以加上下面的配置&ndash;&gt;-->
<!-- <appendAssemblyId>false</appendAssemblyId>-->
<!-- <descriptorRefs>-->
<!-- <descriptorRef>jar-with-dependencies</descriptorRef>-->
<!-- </descriptorRefs>-->
<!-- <archive>-->
<!-- <manifest>-->
<!-- &lt;!&ndash; 是否绑定依赖,将外部 jar 包依赖加入到 classPath 中 &ndash;&gt;-->
<!-- <addClasspath>true</addClasspath>-->
<!-- &lt;!&ndash; 依赖前缀,与之前设置的文件夹路径要匹配 &ndash;&gt;-->
<!-- <classpathPrefix>lib/</classpathPrefix>-->
<!-- &lt;!&ndash; 执行的主程序入口 &ndash;&gt;-->
<!-- <mainClass>org.aohe.scanservice.Main</mainClass>-->
<!-- </manifest>-->
<!-- </archive>-->
<!-- </configuration>-->
<!-- <executions>-->
<!-- <execution>-->
<!-- <id>make-assembly</id>-->
<!-- &lt;!&ndash;绑定的 maven 操作&ndash;&gt;-->
<!-- <phase>package</phase>-->
<!-- <goals>-->
<!-- <goal>assembly</goal>-->
<!-- </goals>-->
<!-- </execution>-->
<!-- </executions>-->
<!-- </plugin>-->
<plugin>
<groupId>org.graalvm.nativeimage</groupId>
<artifactId>native-image-maven-plugin</artifactId>
<version>21.2.0</version>
<executions>
<execution>
<goals>
<goal>native-image</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>scan-service</imageName>
<mainClass>org.aohe.scanservice.Main</mainClass>
<buildArgs>
--no-fallback
</buildArgs>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- <plugin>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-maven-plugin</artifactId>-->
<!-- <configuration>-->
<!-- <excludes>-->
<!-- <exclude>-->
<!-- <groupId>org.projectlombok</groupId>-->
<!-- <artifactId>lombok</artifactId>-->
<!-- </exclude>-->
<!-- </excludes>-->
<!-- </configuration>-->
<!-- </plugin>-->
</plugins>
</build>
</project>

View File

@ -0,0 +1,32 @@
package org.aohe.scanservice;
import cn.hutool.core.net.NetUtil;
import org.aohe.scanservice.web.SocketServer;
import sun.nio.ch.Net;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.concurrent.LinkedBlockingQueue;
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
int port = 8997; // 843 flash policy port
//isInnerIP
SocketServer s = new SocketServer(port);
s.start();
System.out.println("scan-service started on port: " + s.getPort());
BufferedReader sysin = new BufferedReader(new InputStreamReader(System.in));
while (true) {
String in = sysin.readLine();
s.broadcast(in);
if (in.equals("exit")) {
s.stop(1000);
break;
}
}
}
}

View File

@ -0,0 +1,13 @@
//package org.aohe.scanservice;
//
//import org.springframework.boot.SpringApplication;
//import org.springframework.boot.autoconfigure.SpringBootApplication;
//
//@SpringBootApplication
//public class ScanServiceApplication {
//
// public static void main(String[] args) {
// SpringApplication.run(ScanServiceApplication.class, args);
// }
//
//}

View File

@ -0,0 +1,129 @@
package org.aohe.scanservice.control;
import au.com.southsky.jfreesane.SaneDevice;
import au.com.southsky.jfreesane.SaneException;
import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aohe.scanservice.core.SaneSessionUtils;
import org.aohe.scanservice.result.R;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class SaneOperational {
public static String selectOperational(String path) {
JSONObject json = JSONObject.parse(path);
//操作符
String function = json.getString("function");
//参数符
JSONObject param = json.getJSONObject("params");
R r = R.ok();
try {
if("001001".equals(function)){
//获取扫描仪列表
r = getDeviceList();
} else if ("001002".equals(function)) {
//选择扫描仪
r = setScanner(param.getString("scannerId"));
}else if ("001003".equals(function)){
//获取扫描仪操作符列表
// r = getDeviceOperations();
}else if ("001004".equals(function)){
//r = setDeviceOperations();
}else if ("001007".equals(function)){
//r = setDeviceOperations(param);
}else if ("001008".equals(function)){
r = startScan(param);
}else if ("001012".equals(function)){
//closeTwSource();
}else if ("001013".equals(function)){
//closeTwSource();
}else if ("001015".equals(function)){
//r = startScan(param.getString("scannerId"),true);
}else if ("001016".equals(function)){
//r = startScan(param.getString("scannerId"),true);
}
}catch (Exception e){
log.info("Error ", e);
}
return r.toJsonStr();
}
/**
* 001001 获取扫描仪列表
* @return 返回扫描仪列表
*/
public static R getDeviceList(){
try {
List<SaneDevice> saneDevices = SaneSessionUtils.getSaneDrivers();
List<String> names = saneDevices.stream().map(SaneDevice::getName).collect(Collectors.toList());
return R.ok(names);
} catch (IOException | SaneException e) {
log.error("Not found scan list", e);
return R.fail("Not found scan list");
}
}
private static String saneDrivers = null;
/**
* 001002 选择扫描仪
* @param scannerId 扫描仪id
* @return 返回成功
*/
public static R setScanner(String scannerId){
try {
if(saneDrivers == null){
saneDrivers = scannerId;
}
SaneSessionUtils.setSaneDevice(scannerId);
return R.ok();
} catch (SaneException | IOException e) {
throw new RuntimeException(e);
}
}
/**
* 001007 设置扫描仪参数
* @param params 扫描仪参数
* @return 返回成功
*/
// public static R setDeviceOperations(JSONObject params){
// try {
// SaneSeesionUtils.setOption(params);
// } catch (TwainException e) {
// log.error("scan setting is not set", e);
// return R.fail("scan setting is not set, please select scan ");
// }
// return R.ok();
// }
public static R startScan(JSONObject params){
try {
File files = SaneSessionUtils.getSaneFile();
Map<String,String> map = new HashMap<>();
map.put(files.getName(),Base64.encode(files));
List<Map<String,String>> list = new ArrayList<>();
list.add(map);
return R.ok(list);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -0,0 +1,129 @@
package org.aohe.scanservice.control;
import cn.hutool.core.codec.Base64;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aohe.exceptions.TwainException;
import org.aohe.scanservice.core.TwainUtils;
import org.aohe.scanservice.result.R;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
public class TwainOperational{
public static String selectOperational(String path) {
JSONObject json = JSONObject.parse(path);
//操作符
String function = json.getString("function");
//参数符
JSONObject param = json.getJSONObject("params");
R r = R.ok();
try {
if("001001".equals(function)){
//获取扫描仪列表
r = getDeviceList();
} else if ("001002".equals(function)) {
//选择扫描仪
r = setScanner(param.getString("scannerId"));
}else if ("001003".equals(function)){
//获取扫描仪操作符列表
// r = getDeviceOperations();
}else if ("001004".equals(function)){
//r = setDeviceOperations();
}else if ("001007".equals(function)){
r = setDeviceOperations(param);
}else if ("001008".equals(function)){
r = startScan(param);
}else if ("001012".equals(function)){
//closeTwSource();
}else if ("001013".equals(function)){
//closeTwSource();
}else if ("001015".equals(function)){
//r = startScan(param.getString("scannerId"),true);
}else if ("001016".equals(function)){
//r = startScan(param.getString("scannerId"),true);
}
}catch (Exception e){
log.info("Error ", e);
}
return r.toJsonStr();
}
/**
* 001001 获取扫描仪列表
* @return 返回扫描仪列表
*/
public static R getDeviceList(){
try {
return R.ok(TwainUtils.getDeviceList());
} catch (TwainException e) {
log.error("Not found scan list", e);
return R.fail("Not found scan list");
}
}
/**
* 001002 选择扫描仪
* @param scannerId 扫描仪id
* @return 返回成功
*/
public static R setScanner(String scannerId){
try {
TwainUtils.setDevice(scannerId);
return R.ok();
} catch (TwainException e) {
log.error("scan device is not found", e);
return R.fail("scan device is not found");
}
}
/**
* 001007 设置扫描仪参数
* @param params 扫描仪参数
* @return 返回成功
*/
public static R setDeviceOperations(JSONObject params){
try {
TwainUtils.setOption(params);
} catch (TwainException e) {
log.error("scan setting is not set", e);
return R.fail("scan setting is not set, please select scan ");
}
return R.ok();
}
public static R startScan(JSONObject params){
List<Map<String, String>> base64Files;
try {
List<File> files;
if(params != null){
files = TwainUtils.scan(params.getString("scannerId"), params);
}else{
files = TwainUtils.scan();
}
base64Files = files.stream().map(t -> {
Map<String, String> map = new HashMap<>();
map.put(t.getName(), Base64.encode(t));
return map;
}).collect(Collectors.toList());
} catch (TwainException e) {
log.error("scan fail , device has problem", e);
return R.fail("scan fail , device has problem");
}
return R.ok(base64Files);
}
}

View File

@ -0,0 +1,174 @@
package org.aohe.scanservice.core;
import au.com.southsky.jfreesane.SaneDevice;
import au.com.southsky.jfreesane.SaneException;
import au.com.southsky.jfreesane.SaneSession;
import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aohe.scanservice.utils.RemoteConfig;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.util.List;
@Slf4j
public class SaneSessionUtils {
private static final Object lock = new Object();
private static volatile SaneSession saneSession;
private static volatile SaneDevice saneDevice;
private static final RemoteConfig remoteConfig = RemoteConfig.getInstance();
/**
* 获取一个SaneSession实例用于与SANE设备进行通信
* @return SaneSession实例
* @throws IOException 如果获取SaneSession实例时发生I/O错误
*/
public static SaneSession getSaneSession() throws IOException {
log.info("saneSession状态{}", saneSession != null);
if (saneSession == null) {
synchronized(lock){
if (saneSession == null) {
log.info("jFreeSaneConfig:" + JSON.toJSONString(remoteConfig));
InetAddress address = InetAddress.getByName(remoteConfig.getIp());
saneSession = SaneSession.withRemoteSane(address);
log.info("初始化saneSession完成状态{}", saneSession != null);
}
}
}
return saneSession;
}
/**
* 关闭SaneSession对象如果对象不为null
*/
public static void closeSaneSession() {
if (saneSession != null) {
try {
saneSession.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
saneSession = null;
}
}
/**
* 获取所有的SANE驱动器设备列表
*
* @return SANE驱动器设备列表
* @throws IOException 如果在通信中发生I/O错误
* @throws SaneException 如果在与SANE交互中发生错误
*/
public static List<SaneDevice> getSaneDrivers() throws IOException, SaneException {
return getSaneSession().listDevices();
}
/**
* 设置Sane设备
* @param name 设备名称
* @return 设备对象
* @throws IOException 输入/输出异常
* @throws SaneException Sane异常
*/
public static SaneDevice setSaneDevice(String name) throws IOException, SaneException {
if (saneDevice == null || !saneDevice.getName().equals(name)) {
if (saneDevice != null && saneDevice.isOpen()) {
// 关闭当前在使用的SANE设备
saneDevice.close();
}
saneDevice = saneSession
.listDevices().stream().filter(s -> name.equals(s.getName())).findFirst().orElse(null);
}
return saneDevice;
}
/**
* 获取Sane设备如果不存在则返回null
* @return Sane设备
*/
public static SaneDevice getDevice() {
return saneDevice;
}
/**
* 获取指定名称的Sane设备如果设备不存在则返回null
* @param name 设备名称
* @return 指定名称的Sane设备
* @throws RuntimeException 运行时异常
*/
public static SaneDevice getDevice(String name) {
try {
return setSaneDevice(name);
} catch (IOException | SaneException e) {
throw new RuntimeException(e);
}
}
/**
* 获取一个正常的文件
* 打开Sane设备
* 通过Sane设备获取图像
* 创建或更新最后访问时间的文件
* 将图像写入文件
* 返回文件
* @throws RuntimeException - 如果发生I/O错误
*/
public static File getSaneFile() throws IOException {
try {
saneDevice.open();
BufferedImage bufferedImage = saneDevice.acquireImage();
File file = FileUtil.createTempFile("sane","png",true);
ImageIO.write(bufferedImage, "png", file);
return file;
} catch (IOException | SaneException e) {
throw new RuntimeException(e);
}finally {
if(saneDevice != null){
saneDevice.close();
}
}
}
/**
* 释放资源
*/
public static void resource(){
try {
if(saneDevice != null){
closeSaneDevice();
}
if(saneSession != null){
closeSaneSession();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* 关闭Sane设备
*/
public static void closeSaneDevice() throws IOException {
if(saneDevice != null){
try {
saneDevice.close();
} catch (IOException e) {
throw new IOException(e);
}
saneDevice = null;
}
}
}

View File

@ -0,0 +1,161 @@
package org.aohe.scanservice.core;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import org.aohe.core.twain.Twain;
import org.aohe.core.twain.TwainScanner;
import org.aohe.exceptions.TwainException;
import org.aohe.scan.Source;
import org.aohe.scan.SourceManager;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
public class TwainUtils {
private static String deviceName = null;
private static Collection<Source> sources = null;
private static Source source = null;
/**
* 获取设备列表
* @return 设备列表
* @throws TwainException 系统错误
*/
public static List<String> getDeviceList() throws TwainException {
sources = SourceManager.instance().getSources();
return sources.stream().map(Source::getName).collect(Collectors.toList());
}
/**
* 设置设备
* @param name 设备名称
* @throws TwainException 系统错误
*/
public static void setDevice(String name) throws TwainException {
if(name != null && !name.equals(deviceName)){
for(Source s : getSources()){
if(StrUtil.equals(s.getName(), name)){
deviceName = name;
source = s;
//默认不使用系统UI
source.setSystemUI(false);
TwainScanner.getScanner().select(name);
Twain.getSourceManager().selectSource(name);
break;
}
}
if(source == null){
throw new TwainException("scan device is not found");
}
}
}
/**
* BW - 0
* COLOR - 2
* GRAYSCALE - 1
* true ->auto
* @param params
*/
/**
* 设置参数
* @param params 参数 Dpi ->double 0-bw 2-color 1-gray true-auto
* @throws TwainException 系统错误
*/
public static void setOption(JSONObject params) throws TwainException {
if(source == null){
throw new TwainException("please first set device");
}
if(params == null){
return;
}
Double key = params.getDouble("dpi");
if(key != null){
source.setDpi(key.intValue());
}
Integer mode = params.getInteger("mode");
if(mode != null){
switch (mode){
case 0:
source.setColor(Source.ColorMode.BW);
break;
case 1:
source.setColor(Source.ColorMode.GRAYSCALE);
break;
case 2:
default:
source.setColor(Source.ColorMode.COLOR);
}
}
Boolean paperMode = params.getBoolean("paperMode");
if(paperMode != null){
source.setAutoDocumentFeeder(paperMode);
}
Boolean systemUI = params.getBoolean("systemUI");
if(systemUI != null){
source.setSystemUI(systemUI);
}
}
/**
* 扫描
* @param name 设备名称
* @param params 参数
* @return 文件列表
*/
public static List<File> scan(String name, JSONObject params) throws TwainException {
source = getSource(name);
setOption(params);
return source.scan();
}
/**
* 使用已选中的扫描仪扫描
* @return 文件列表
*/
public static List<File> scan() throws TwainException {
return scan(deviceName, null);
}
/**
* 获取设备
* @param name 设备名称
* @return 设备
*/
public static Source getSource(String name){
return sources.stream().filter(source -> source.getName().equals(name)).findFirst().orElse(null);
}
public static Collection<Source> getSources() throws TwainException {
if(sources == null || sources.isEmpty()){
sources = SourceManager.instance().getSources();
}
return sources;
}
// public static void main(String[] args) throws TwainException {
// Collection<Source> sda = SourceManager.instance().getSources();
// Source source = sda.stream().findFirst().get();
// source.setDpi(200);
// source.setColor(Source.ColorMode.COLOR);
// List<File> files = source.scan();
// System.out.println(files.get(0).getName());
// }
/**
* 重置
*/
public static void resource(){
deviceName = null;
sources = null;
source = null;
}
}

View File

@ -0,0 +1,39 @@
package org.aohe.scanservice.result;
import cn.hutool.json.JSONUtil;
import lombok.Data;
@Data
public class R<T> {
private String code;
private String msg;
private T data;
private boolean success;
public R (String code, String msg, T data, boolean success) {
this.code = code;
this.msg = msg;
this.data = data;
this.success = success;
}
public static R ok(Object data) {
return new R<>("200", "ok", data, true);
}
public static R ok() {
return new R<>("200", "ok", null, true);
}
public static R fail(String msg) {
return new R<>("500", msg, null, false);
}
public String toJsonStr() {
return JSONUtil.toJsonStr(this);
}
}

View File

@ -0,0 +1,27 @@
package org.aohe.scanservice.utils;
import cn.hutool.setting.Setting;
import lombok.Data;
@Data
public class RemoteConfig {
private String ip = "127.0.0.1";
RemoteConfig() {
}
RemoteConfig(String ip) {
this.ip = ip;
}
public static RemoteConfig getInstance(){
String ip = new Setting("config.setting").get("ip");
if(ip != null){
return new RemoteConfig(ip);
}
return new RemoteConfig();
}
}

View File

@ -0,0 +1,48 @@
package org.aohe.scanservice.utils;
public class SystemUtils {
/**
* 判断操作系统是否是 Windows
*
* @return true操作系统是 Windows
* false其它操作系统
*/
public static boolean isWindows() {
String osName = getOsName();
return osName != null && osName.startsWith("Windows");
}
/**
* 判断操作系统是否是 MacOS
*
* @return true操作系统是 MacOS
* false其它操作系统
*/
public static boolean isMacOs() {
String osName = getOsName();
return osName != null && osName.startsWith("Mac");
}
/**
* 判断操作系统是否是 Linux
*
* @return true操作系统是 Linux
* false其它操作系统
*/
public static boolean isLinux() {
String osName = getOsName();
return (osName != null && osName.startsWith("Linux")) || (!isWindows() && !isMacOs());
}
/**
* 获取操作系统名称
* @return os.name 属性值
*/
public static String getOsName() {
return System.getProperty("os.name");
}
}

View File

@ -0,0 +1,74 @@
//package org.aohe.scanservice.web;
//
//import cn.hutool.system.SystemUtil;
//import jakarta.websocket.*;
//import jakarta.websocket.server.ServerEndpoint;
//import lombok.extern.slf4j.Slf4j;
//import org.aohe.scanservice.control.TwainOperational;
//import org.aohe.scanservice.result.R;
//import org.springframework.stereotype.Component;
//
//@Slf4j
//@ServerEndpoint("/scanSocket")// 接口路径 ws://localhost:8087/webSocket/userId;
//@Component
//public class ScanSocket {
//
//
// /**
// * 链接成功调用的方法
// */
// @OnOpen
// public void onOpen() {
// log.info("客户端已接入,当前客户端系统为:{}", SystemUtil.getOsInfo().getName());
// }
//
// /**
// * 链接关闭调用的方法
// */
// @OnClose
// public void onClose() {
// log.info("客户端已断开,客户端系统为:{}", SystemUtil.getOsInfo().getName());
// }
// /**
// * 收到客户端消息后调用的方法
// *
// * @param message
// */
// @OnMessage
// public String onMessage(String message) {
// log.info("【websocket 消息】收到客户端消息:"+message);
// String result ;
// if (SystemUtil.getOsInfo().isWindows()) {
// result = TwainOperational.selectOperational(message);
// } else if(SystemUtil.getOsInfo().isLinux()) {
// result = R.ok("还在更新,稍等...").toJsonStr();
// }else {
// result = R.fail("无对应操作系统").toJsonStr();
// }
// return result;
// }
//
// /** 发送错误时的处理
// * @param session
// * @param error
// */
// @OnError
// public void onError(Session session, Throwable error) {
// log.error("用户错误,原因:"+error.getMessage());
// }
//
//
// // 此为广播消息
// public void sendAllMessage(String message) {
// log.info("【websocket 消息】广播消息:"+message);
// }
//
// // 此为单点消息
// public void sendOneMessage(String userId, String message) {
// }
//
// // 此为单点消息(多人)
// public void sendMoreMessage(String[] userIds, String message) {
// }
//
//}

View File

@ -0,0 +1,92 @@
package org.aohe.scanservice.web;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import org.aohe.scanservice.control.SaneOperational;
import org.aohe.scanservice.control.TwainOperational;
import org.aohe.scanservice.core.SaneSessionUtils;
import org.aohe.scanservice.core.TwainUtils;
import org.aohe.scanservice.result.R;
import org.aohe.scanservice.utils.SystemUtils;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
public class SocketServer extends WebSocketServer {
private static final Log log = LogFactory.get();
public SocketServer(int port) throws UnknownHostException {
super(new InetSocketAddress(port));
}
public SocketServer(int port, String path) throws UnknownHostException {
super(new InetSocketAddress(port));
}
public SocketServer(InetSocketAddress address) {
super(address);
}
@Override
public void onOpen(WebSocket conn, ClientHandshake handshake) {
conn.send("Welcome to the scan-server!"); // This method sends a message to the new client
//broadcast("new connection: " + handshake.getResourceDescriptor()); // This method sends a message to all clients connected
//System.out.println(conn.getRemoteSocketAddress().getAddress().getHostAddress() + " entered the room!");
log.info("client is open ,client system is: {}", SystemUtils.getOsName());
}
@Override
public void onClose(WebSocket conn, int code, String reason, boolean remote) {
log.info("client is closed , client system is : {}", SystemUtils.getOsName());
//这里执行关闭扫描仪连接
if(SystemUtils.isWindows()){
TwainUtils.resource();
} else if (SystemUtils.isLinux()) {
SaneSessionUtils.resource();
}
}
@Override
public void onMessage(WebSocket conn, String message) {
log.info("User send Data: \n"+message);
String result;
if(!JSONUtil.isTypeJSON(message)){
result = R.fail("Illegal parameters, not of json type").toJsonStr();
}else {
if (SystemUtils.isWindows()) {
result = TwainOperational.selectOperational(message);
} else if(SystemUtils.isLinux()) {
result = SaneOperational.selectOperational(message);
}else {
result = R.fail("No corresponding operating system").toJsonStr();
}
}
log.info("Return data: \n"+result);
conn.send(result);
}
@Override
public void onError(WebSocket conn, Exception ex) {
log.error("error :"+ex.getMessage(),ex);
if (conn != null) {
//绑定不到就退出
//System.exit(0);
// some errors like port binding failed may not be assignable to a specific
// websocket
}
}
@Override
public void onStart() {
System.out.println("Server started!");
setConnectionLostTimeout(0);
setConnectionLostTimeout(100);
}
}

View File

@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: org.aohe.scanservice.Main

View File

@ -0,0 +1,171 @@
[
{
"name":"[Ljava.lang.Object;"
},
{
"name":"com.sun.jna.Callback"
},
{
"name":"com.sun.jna.CallbackProxy",
"methods":[{"name":"callback","parameterTypes":["java.lang.Object[]"] }]
},
{
"name":"com.sun.jna.CallbackReference",
"methods":[{"name":"getCallback","parameterTypes":["java.lang.Class","com.sun.jna.Pointer","boolean"] }, {"name":"getFunctionPointer","parameterTypes":["com.sun.jna.Callback","boolean"] }, {"name":"getNativeString","parameterTypes":["java.lang.Object","boolean"] }, {"name":"initializeThread","parameterTypes":["com.sun.jna.Callback","com.sun.jna.CallbackReference$AttachOptions"] }]
},
{
"name":"com.sun.jna.CallbackReference$AttachOptions"
},
{
"name":"com.sun.jna.IntegerType",
"fields":[{"name":"value"}]
},
{
"name":"com.sun.jna.JNIEnv"
},
{
"name":"com.sun.jna.Native",
"methods":[{"name":"dispose","parameterTypes":[] }, {"name":"fromNative","parameterTypes":["com.sun.jna.FromNativeConverter","java.lang.Object","java.lang.reflect.Method"] }, {"name":"fromNative","parameterTypes":["java.lang.Class","java.lang.Object"] }, {"name":"fromNative","parameterTypes":["java.lang.reflect.Method","java.lang.Object"] }, {"name":"nativeType","parameterTypes":["java.lang.Class"] }, {"name":"toNative","parameterTypes":["com.sun.jna.ToNativeConverter","java.lang.Object"] }]
},
{
"name":"com.sun.jna.Native$ffi_callback",
"methods":[{"name":"invoke","parameterTypes":["long","long","long"] }]
},
{
"name":"com.sun.jna.NativeMapped",
"methods":[{"name":"toNative","parameterTypes":[] }]
},
{
"name":"com.sun.jna.Pointer",
"fields":[{"name":"peer"}],
"methods":[{"name":"<init>","parameterTypes":["long"] }]
},
{
"name":"com.sun.jna.PointerType",
"fields":[{"name":"pointer"}]
},
{
"name":"com.sun.jna.Structure",
"fields":[{"name":"memory"}, {"name":"typeInfo"}],
"methods":[{"name":"autoRead","parameterTypes":[] }, {"name":"autoWrite","parameterTypes":[] }, {"name":"getTypeInfo","parameterTypes":[] }, {"name":"newInstance","parameterTypes":["java.lang.Class","long"] }]
},
{
"name":"com.sun.jna.Structure$ByValue"
},
{
"name":"com.sun.jna.Structure$FFIType$FFITypes",
"fields":[{"name":"ffi_type_double"}, {"name":"ffi_type_float"}, {"name":"ffi_type_longdouble"}, {"name":"ffi_type_pointer"}, {"name":"ffi_type_sint16"}, {"name":"ffi_type_sint32"}, {"name":"ffi_type_sint64"}, {"name":"ffi_type_sint8"}, {"name":"ffi_type_uint16"}, {"name":"ffi_type_uint32"}, {"name":"ffi_type_uint64"}, {"name":"ffi_type_uint8"}, {"name":"ffi_type_void"}]
},
{
"name":"com.sun.jna.WString",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.lang.Boolean",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["boolean"] }, {"name":"getBoolean","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.lang.Byte",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["byte"] }]
},
{
"name":"java.lang.Character",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["char"] }]
},
{
"name":"java.lang.Class",
"methods":[{"name":"getComponentType","parameterTypes":[] }]
},
{
"name":"java.lang.Double",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["double"] }]
},
{
"name":"java.lang.Float",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["float"] }]
},
{
"name":"java.lang.Integer",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["int"] }]
},
{
"name":"java.lang.Long",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["long"] }]
},
{
"name":"java.lang.Object",
"methods":[{"name":"toString","parameterTypes":[] }]
},
{
"name":"java.lang.SecurityManager",
"fields":[{"name":"initialized"}]
},
{
"name":"java.lang.Short",
"fields":[{"name":"TYPE"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["short"] }]
},
{
"name":"java.lang.String",
"methods":[{"name":"<init>","parameterTypes":["byte[]"] }, {"name":"<init>","parameterTypes":["byte[]","java.lang.String"] }, {"name":"getBytes","parameterTypes":[] }, {"name":"getBytes","parameterTypes":["java.lang.String"] }, {"name":"toCharArray","parameterTypes":[] }]
},
{
"name":"java.lang.System",
"methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.lang.UnsatisfiedLinkError",
"methods":[{"name":"<init>","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.lang.Void",
"fields":[{"name":"TYPE"}]
},
{
"name":"java.lang.reflect.Method",
"methods":[{"name":"getParameterTypes","parameterTypes":[] }, {"name":"getReturnType","parameterTypes":[] }]
},
{
"name":"java.nio.Buffer",
"methods":[{"name":"position","parameterTypes":[] }]
},
{
"name":"java.nio.ByteBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"java.nio.CharBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"java.nio.DoubleBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"java.nio.FloatBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"java.nio.IntBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"java.nio.LongBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"java.nio.ShortBuffer",
"methods":[{"name":"array","parameterTypes":[] }, {"name":"arrayOffset","parameterTypes":[] }]
},
{
"name":"sun.management.VMManagementImpl",
"fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}]
}
]

View File

@ -0,0 +1,8 @@
[
{
"type":"agent-extracted",
"classes":[
]
}
]

View File

@ -0,0 +1,11 @@
[
{
"interfaces":["com.sun.jna.platform.win32.User32"]
},
{
"interfaces":["free.lucifer.jtwain.libs.Kernel32"]
},
{
"interfaces":["free.lucifer.jtwain.libs.Win32Twain"]
}
]

View File

@ -0,0 +1,221 @@
[
{
"name":"[B",
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"[Ljava.lang.reflect.Method;"
},
{
"name":"byte",
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"com.alibaba.fastjson.JSONArray"
},
{
"name":"com.alibaba.fastjson.JSONObject"
},
{
"name":"com.alibaba.fastjson2.JSONFactory$CacheItem",
"fields":[{"name":"bytes"}, {"name":"chars"}]
},
{
"name":"com.alibaba.fastjson2.JSONObject",
"queryAllDeclaredConstructors":true
},
{
"name":"com.alibaba.fastjson2.util.TypeUtils$Cache",
"fields":[{"name":"chars"}]
},
{
"name":"com.sun.jna.CallbackProxy",
"methods":[{"name":"callback","parameterTypes":["java.lang.Object[]"] }]
},
{
"name":"com.sun.jna.Structure$FFIType",
"allDeclaredFields":true,
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"com.sun.jna.Structure$FFIType$size_t",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$ATOM",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$HBRUSH",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$HCURSOR",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$HICON",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$HINSTANCE",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$HWND",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$LPARAM",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$LRESULT",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$POINT",
"allDeclaredFields":true,
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}],
"methods":[{"name":"<init>","parameterTypes":["com.sun.jna.Pointer"] }]
},
{
"name":"com.sun.jna.platform.win32.WinDef$WPARAM",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinNT$HANDLEByReference",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.jna.platform.win32.WinUser$MSG",
"allDeclaredFields":true,
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"com.sun.jna.platform.win32.WinUser$WNDCLASSEX",
"allDeclaredFields":true,
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"com.sun.jna.platform.win32.WinUser$WindowProc",
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"methods":[{"name":"callback","parameterTypes":["com.sun.jna.platform.win32.WinDef$HWND","int","com.sun.jna.platform.win32.WinDef$WPARAM","com.sun.jna.platform.win32.WinDef$LPARAM"] }]
},
{
"name":"free.lucifer.jtwain.TwainWndProc",
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"free.lucifer.jtwain.libs.Win32Twain$TW_IDENTITY",
"allDeclaredFields":true
},
{
"name":"free.lucifer.jtwain.libs.Win32Twain$TW_VERSION",
"allDeclaredFields":true,
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"<init>","parameterTypes":["com.sun.jna.Pointer"] }]
},
{
"name":"java.beans.Transient"
},
{
"name":"java.lang.Object",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"methods":[{"name":"equals","parameterTypes":["java.lang.Object"] }, {"name":"hashCode","parameterTypes":[] }, {"name":"toString","parameterTypes":[] }]
},
{
"name":"java.lang.String",
"fields":[{"name":"COMPACT_STRINGS"}, {"name":"coder"}, {"name":"value"}],
"methods":[{"name":"<init>","parameterTypes":["byte[]","byte"] }, {"name":"coder","parameterTypes":[] }, {"name":"isASCII","parameterTypes":["byte[]"] }, {"name":"value","parameterTypes":[] }]
},
{
"name":"java.lang.StringCoding",
"methods":[{"name":"hasNegatives","parameterTypes":["byte[]","int","int"] }]
},
{
"name":"java.lang.invoke.MethodHandles$Lookup",
"fields":[{"name":"IMPL_LOOKUP"}],
"methods":[{"name":"<init>","parameterTypes":["java.lang.Class","java.lang.Class","int"] }]
},
{
"name":"java.lang.management.ManagementFactory",
"methods":[{"name":"getRuntimeMXBean","parameterTypes":[] }]
},
{
"name":"java.lang.management.RuntimeMXBean",
"methods":[{"name":"getInputArguments","parameterTypes":[] }]
},
{
"name":"java.lang.reflect.Method",
"methods":[{"name":"isVarArgs","parameterTypes":[] }]
},
{
"name":"java.math.BigDecimal",
"fields":[{"name":"intCompact"}]
},
{
"name":"java.math.BigInteger",
"fields":[{"name":"mag"}]
},
{
"name":"java.nio.Buffer"
},
{
"name":"java.security.SecureRandomParameters"
},
{
"name":"java.sql.Date"
},
{
"name":"java.sql.Timestamp"
},
{
"name":"java.util.Collections$UnmodifiableCollection"
},
{
"name":"java.util.Collections$UnmodifiableMap"
},
{
"name":"java.util.concurrent.atomic.AtomicBoolean",
"fields":[{"name":"value"}]
},
{
"name":"java.util.concurrent.atomic.AtomicReference",
"fields":[{"name":"value"}]
},
{
"name":"javax.sql.DataSource"
},
{
"name":"javax.sql.RowSet"
},
{
"name":"org.aohe.scanservice.result.R",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"queryAllPublicMethods":true,
"methods":[{"name":"getCode","parameterTypes":[] }, {"name":"getData","parameterTypes":[] }, {"name":"getMsg","parameterTypes":[] }, {"name":"isSuccess","parameterTypes":[] }]
},
{
"name":"short",
"fields":[{"name":"OPTIONS"}, {"name":"STRING_ENCODING"}, {"name":"STRUCTURE_ALIGNMENT"}, {"name":"TYPE_MAPPER"}]
},
{
"name":"sun.misc.Unsafe",
"fields":[{"name":"theUnsafe"}]
},
{
"name":"sun.security.provider.DRBG",
"methods":[{"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
},
{
"name":"sun.security.provider.SHA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.SHA2$SHA256",
"methods":[{"name":"<init>","parameterTypes":[] }]
}
]

View File

@ -0,0 +1,9 @@
{
"resources":{
"includes":[{
"pattern":"\\QMETA-INF/services/cn.hutool.log.LogFactory\\E"
}, {
"pattern":"\\Qcom/sun/jna/win32-x86-64/jnidispatch.dll\\E"
}]},
"bundles":[]
}

View File

@ -0,0 +1,8 @@
{
"types":[
],
"lambdaCapturingTypes":[
],
"proxies":[
]
}

View File

@ -0,0 +1,2 @@
server:
port: 8997

View File

@ -0,0 +1,2 @@
[remote]
ip = 127.0.0.1

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- 日志存放路径 -->
<property name="log.path" value="./Logs/ScanService"/>
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 全部日志输出 -->
<appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/scanService.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
<totalSizeCap>20GB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.aohe" level="info"/>
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn"/>
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
</configuration>