commit 24b498dbd0c332c18c948597308cc9dc22a18643 Author: 刘福顺 Date: Mon May 20 17:43:59 2024 +0800 1. 首次提交 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..549e00a --- /dev/null +++ b/.gitignore @@ -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/ diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar new file mode 100644 index 0000000..cb28b0e Binary files /dev/null and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000..5f0536e --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -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 diff --git a/jniconfig.json b/jniconfig.json new file mode 100644 index 0000000..d18a7af --- /dev/null +++ b/jniconfig.json @@ -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" : "", "parameterTypes" : [] }, + { "name" : "getParam", "parameterTypes" : [] }, + { "name" : "setInfo", "parameterTypes" : ["byte[]", "int"] } + ] + } +] \ No newline at end of file diff --git a/mvnw b/mvnw new file mode 100644 index 0000000..66df285 --- /dev/null +++ b/mvnw @@ -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 "$@" diff --git a/mvnw.cmd b/mvnw.cmd new file mode 100644 index 0000000..95ba6f5 --- /dev/null +++ b/mvnw.cmd @@ -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% diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..e75fb09 --- /dev/null +++ b/pom.xml @@ -0,0 +1,147 @@ + + + 4.0.0 + + + + + + + org.aohe + scan-service + 0.0.1-SNAPSHOT + scan-service + scan-service + + 8 + UTF-8 + + + + + org.java-websocket + Java-WebSocket + 1.5.3 + + + cn.hutool + hutool-all + 5.8.25 + + + com.googlecode.jfreesane + jfreesane + 1.0 + + + + com.alibaba.fastjson2 + fastjson2 + 2.0.45 + + + + org.projectlombok + lombok + true + 1.18.30 + + + + org.aohe + twain-service + 0.1.1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.graalvm.nativeimage + native-image-maven-plugin + 21.2.0 + + + + native-image + + package + + + + false + scan-service + org.aohe.scanservice.Main + + --no-fallback + + + + + maven-dependency-plugin + + + package + + copy-dependencies + + + ${project.build.directory}/lib + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/aohe/scanservice/Main.java b/src/main/java/org/aohe/scanservice/Main.java new file mode 100644 index 0000000..fd579cc --- /dev/null +++ b/src/main/java/org/aohe/scanservice/Main.java @@ -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; + } + } + } +} diff --git a/src/main/java/org/aohe/scanservice/ScanServiceApplication.java b/src/main/java/org/aohe/scanservice/ScanServiceApplication.java new file mode 100644 index 0000000..42ada63 --- /dev/null +++ b/src/main/java/org/aohe/scanservice/ScanServiceApplication.java @@ -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); +// } +// +//} diff --git a/src/main/java/org/aohe/scanservice/control/SaneOperational.java b/src/main/java/org/aohe/scanservice/control/SaneOperational.java new file mode 100644 index 0000000..17868dc --- /dev/null +++ b/src/main/java/org/aohe/scanservice/control/SaneOperational.java @@ -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 saneDevices = SaneSessionUtils.getSaneDrivers(); + List 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 map = new HashMap<>(); + map.put(files.getName(),Base64.encode(files)); + List> list = new ArrayList<>(); + list.add(map); + + return R.ok(list); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/org/aohe/scanservice/control/TwainOperational.java b/src/main/java/org/aohe/scanservice/control/TwainOperational.java new file mode 100644 index 0000000..2a77fe5 --- /dev/null +++ b/src/main/java/org/aohe/scanservice/control/TwainOperational.java @@ -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> base64Files; + try { + + List files; + if(params != null){ + files = TwainUtils.scan(params.getString("scannerId"), params); + }else{ + files = TwainUtils.scan(); + } + + base64Files = files.stream().map(t -> { + Map 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); + } + +} diff --git a/src/main/java/org/aohe/scanservice/core/SaneSessionUtils.java b/src/main/java/org/aohe/scanservice/core/SaneSessionUtils.java new file mode 100644 index 0000000..36bb729 --- /dev/null +++ b/src/main/java/org/aohe/scanservice/core/SaneSessionUtils.java @@ -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 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; + } + + } + +} + diff --git a/src/main/java/org/aohe/scanservice/core/TwainUtils.java b/src/main/java/org/aohe/scanservice/core/TwainUtils.java new file mode 100644 index 0000000..d67fbe5 --- /dev/null +++ b/src/main/java/org/aohe/scanservice/core/TwainUtils.java @@ -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 sources = null; + + private static Source source = null; + /** + * 获取设备列表 + * @return 设备列表 + * @throws TwainException 系统错误 + */ + public static List 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 scan(String name, JSONObject params) throws TwainException { + source = getSource(name); + setOption(params); + return source.scan(); + } + + /** + * 使用已选中的扫描仪扫描 + * @return 文件列表 + */ + public static List 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 getSources() throws TwainException { + if(sources == null || sources.isEmpty()){ + sources = SourceManager.instance().getSources(); + } + return sources; + } + +// public static void main(String[] args) throws TwainException { +// Collection sda = SourceManager.instance().getSources(); +// Source source = sda.stream().findFirst().get(); +// source.setDpi(200); +// source.setColor(Source.ColorMode.COLOR); +// List files = source.scan(); +// System.out.println(files.get(0).getName()); +// } + + /** + * 重置 + */ + public static void resource(){ + deviceName = null; + sources = null; + source = null; + } +} diff --git a/src/main/java/org/aohe/scanservice/result/R.java b/src/main/java/org/aohe/scanservice/result/R.java new file mode 100644 index 0000000..4dab19f --- /dev/null +++ b/src/main/java/org/aohe/scanservice/result/R.java @@ -0,0 +1,39 @@ +package org.aohe.scanservice.result; +import cn.hutool.json.JSONUtil; +import lombok.Data; + +@Data +public class R { + + 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); + } +} + diff --git a/src/main/java/org/aohe/scanservice/utils/RemoteConfig.java b/src/main/java/org/aohe/scanservice/utils/RemoteConfig.java new file mode 100644 index 0000000..978d216 --- /dev/null +++ b/src/main/java/org/aohe/scanservice/utils/RemoteConfig.java @@ -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(); + } + +} diff --git a/src/main/java/org/aohe/scanservice/utils/SystemUtils.java b/src/main/java/org/aohe/scanservice/utils/SystemUtils.java new file mode 100644 index 0000000..622910d --- /dev/null +++ b/src/main/java/org/aohe/scanservice/utils/SystemUtils.java @@ -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"); + } +} \ No newline at end of file diff --git a/src/main/java/org/aohe/scanservice/web/ScanSocket.java b/src/main/java/org/aohe/scanservice/web/ScanSocket.java new file mode 100644 index 0000000..0d3cf13 --- /dev/null +++ b/src/main/java/org/aohe/scanservice/web/ScanSocket.java @@ -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) { +// } +// +//} diff --git a/src/main/java/org/aohe/scanservice/web/SocketServer.java b/src/main/java/org/aohe/scanservice/web/SocketServer.java new file mode 100644 index 0000000..bad3f5d --- /dev/null +++ b/src/main/java/org/aohe/scanservice/web/SocketServer.java @@ -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); + + } +} diff --git a/src/main/resources/META-INF/MANIFEST.MF b/src/main/resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..d20ba44 --- /dev/null +++ b/src/main/resources/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: org.aohe.scanservice.Main + diff --git a/src/main/resources/META-INF/native-image/jni-config.json b/src/main/resources/META-INF/native-image/jni-config.json new file mode 100644 index 0000000..25811b5 --- /dev/null +++ b/src/main/resources/META-INF/native-image/jni-config.json @@ -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":"","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":"","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Boolean", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["boolean"] }, {"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.Byte", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["byte"] }] +}, +{ + "name":"java.lang.Character", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["char"] }] +}, +{ + "name":"java.lang.Class", + "methods":[{"name":"getComponentType","parameterTypes":[] }] +}, +{ + "name":"java.lang.Double", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["double"] }] +}, +{ + "name":"java.lang.Float", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["float"] }] +}, +{ + "name":"java.lang.Integer", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.Long", + "fields":[{"name":"TYPE"}, {"name":"value"}], + "methods":[{"name":"","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":"","parameterTypes":["short"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"","parameterTypes":["byte[]"] }, {"name":"","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":"","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"}] +} +] diff --git a/src/main/resources/META-INF/native-image/predefined-classes-config.json b/src/main/resources/META-INF/native-image/predefined-classes-config.json new file mode 100644 index 0000000..0e79b2c --- /dev/null +++ b/src/main/resources/META-INF/native-image/predefined-classes-config.json @@ -0,0 +1,8 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] + diff --git a/src/main/resources/META-INF/native-image/proxy-config.json b/src/main/resources/META-INF/native-image/proxy-config.json new file mode 100644 index 0000000..1e7aedf --- /dev/null +++ b/src/main/resources/META-INF/native-image/proxy-config.json @@ -0,0 +1,11 @@ +[ + { + "interfaces":["com.sun.jna.platform.win32.User32"] + }, + { + "interfaces":["free.lucifer.jtwain.libs.Kernel32"] + }, + { + "interfaces":["free.lucifer.jtwain.libs.Win32Twain"] + } +] diff --git a/src/main/resources/META-INF/native-image/reflect-config.json b/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 0000000..b12ff2e --- /dev/null +++ b/src/main/resources/META-INF/native-image/reflect-config.json @@ -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":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$ATOM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$HBRUSH", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$HCURSOR", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$HICON", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$HINSTANCE", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$HWND", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$LPARAM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$LRESULT", + "methods":[{"name":"","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":"","parameterTypes":["com.sun.jna.Pointer"] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinDef$WPARAM", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.sun.jna.platform.win32.WinNT$HANDLEByReference", + "methods":[{"name":"","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":"","parameterTypes":[] }, {"name":"","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":"","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":"","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":"","parameterTypes":["java.security.SecureRandomParameters"] }] +}, +{ + "name":"sun.security.provider.SHA", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"sun.security.provider.SHA2$SHA256", + "methods":[{"name":"","parameterTypes":[] }] +} +] diff --git a/src/main/resources/META-INF/native-image/resource-config.json b/src/main/resources/META-INF/native-image/resource-config.json new file mode 100644 index 0000000..d35c7fb --- /dev/null +++ b/src/main/resources/META-INF/native-image/resource-config.json @@ -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":[] +} diff --git a/src/main/resources/META-INF/native-image/serialization-config.json b/src/main/resources/META-INF/native-image/serialization-config.json new file mode 100644 index 0000000..f3d7e06 --- /dev/null +++ b/src/main/resources/META-INF/native-image/serialization-config.json @@ -0,0 +1,8 @@ +{ + "types":[ + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..db2a49a --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 8997 diff --git a/src/main/resources/config.setting b/src/main/resources/config.setting new file mode 100644 index 0000000..fcdfb22 --- /dev/null +++ b/src/main/resources/config.setting @@ -0,0 +1,2 @@ +[remote] +ip = 127.0.0.1 \ No newline at end of file diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml new file mode 100644 index 0000000..5729bff --- /dev/null +++ b/src/main/resources/logback.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + ${log.pattern} + + + + + + + + + ${log.path}/scanService.%d{yyyy-MM-dd}.log + + 60 + 20GB + + + ${log.pattern} + + + + + + + + + + + + + + +