Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
mica
mica-auto
提交
6017ad41
mica-auto
项目概览
mica
/
mica-auto
通知
6
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
mica-auto
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
6017ad41
编写于
12月 05, 2019
作者:
如梦技术
🐛
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
🔖
v1.2.0
上级
a4b6abec
变更
8
隐藏空白更改
内联
并排
Showing
8 changed file
with
481 addition
and
41 deletion
+481
-41
CHANGELOG.md
CHANGELOG.md
+5
-0
build.gradle
build.gradle
+8
-3
src/main/java/net/dreamlu/mica/auto/annotation/AutoService.java
...in/java/net/dreamlu/mica/auto/annotation/AutoService.java
+47
-0
src/main/java/net/dreamlu/mica/auto/common/AbstractMicaProcessor.java
...a/net/dreamlu/mica/auto/common/AbstractMicaProcessor.java
+111
-4
src/main/java/net/dreamlu/mica/auto/common/BootAutoType.java
src/main/java/net/dreamlu/mica/auto/common/BootAutoType.java
+2
-2
src/main/java/net/dreamlu/mica/auto/factories/AutoFactoriesProcessor.java
...t/dreamlu/mica/auto/factories/AutoFactoriesProcessor.java
+0
-32
src/main/java/net/dreamlu/mica/auto/service/AutoServiceProcessor.java
...a/net/dreamlu/mica/auto/service/AutoServiceProcessor.java
+228
-0
src/main/java/net/dreamlu/mica/auto/service/ServicesFiles.java
...ain/java/net/dreamlu/mica/auto/service/ServicesFiles.java
+80
-0
未找到文件。
CHANGELOG.md
浏览文件 @
6017ad41
# 变更记录
## 发行版本
## [1.2.0] - 2019-12-06
### 添加
-
添加对 java spi 的支持,并精简代码。
-
lombok、spring boot、google auto 依赖升级。
## [1.1.0] - 2019-05-24
### 添加
-
添加
`@AutoContextInitializer`
支持
`org.springframework.context.ApplicationContextInitializer`
。
...
...
build.gradle
浏览文件 @
6017ad41
...
...
@@ -3,14 +3,19 @@ apply from: "${rootProject.projectDir}/gradle/publish-maven.gradle"
ext
{
javaVersion
=
JavaVersion
.
VERSION_1_8
springBootVersion
=
"2.
1.5
.RELEASE"
lombokVersion
=
"1.18.
8
"
googleAutoServiceVersion
=
"1.0-rc
5
"
springBootVersion
=
"2.
2.1
.RELEASE"
lombokVersion
=
"1.18.
10
"
googleAutoServiceVersion
=
"1.0-rc
6
"
}
group
=
GROUPID
version
=
VERSION
tasks
.
withType
(
JavaCompile
)
{
options
.
encoding
=
"UTF-8"
options
.
compilerArgs
<<
"-Xlint:unchecked"
<<
"-Xlint:deprecation"
}
dependencies
{
api
"org.springframework.boot:spring-boot-configuration-processor:$springBootVersion"
api
"org.springframework.boot:spring-boot-autoconfigure-processor:$springBootVersion"
...
...
src/main/java/net/dreamlu/mica/auto/annotation/AutoService.java
0 → 100644
浏览文件 @
6017ad41
/*
* Copyright 2008 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
net.dreamlu.mica.auto.annotation
;
import
java.lang.annotation.*
;
/**
* An annotation for service providers as described in {@link java.util.ServiceLoader}. The {@link
* net.dreamlu.mica.auto.service.AutoServiceProcessor} generates the configuration files which
* allows service providers to be loaded with {@link java.util.ServiceLoader#load(Class)}.
*
* <p>Service providers assert that they conform to the service provider specification.
* Specifically, they must:
*
* <ul>
* <li>be a non-inner, non-anonymous, concrete class
* <li>have a publicly accessible no-arg constructor
* <li>implement the interface type returned by {@code value()}
* </ul>
*
* @author google
*/
@Documented
@Retention
(
RetentionPolicy
.
SOURCE
)
@Target
(
ElementType
.
TYPE
)
public
@interface
AutoService
{
/**
* Returns the interfaces implemented by this service provider.
*
* @return interface array
*/
Class
<?>[]
value
();
}
src/main/java/net/dreamlu/mica/auto/common/AbstractMicaProcessor.java
浏览文件 @
6017ad41
...
...
@@ -19,12 +19,12 @@ package net.dreamlu.mica.auto.common;
import
javax.annotation.processing.AbstractProcessor
;
import
javax.annotation.processing.RoundEnvironment
;
import
javax.lang.model.SourceVersion
;
import
javax.lang.model.element.AnnotationMirror
;
import
javax.lang.model.element.Element
;
import
javax.lang.model.element.TypeElement
;
import
javax.lang.model.element.*
;
import
javax.lang.model.util.Elements
;
import
javax.tools.Diagnostic.Kind
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.util.List
;
import
java.util.Set
;
/**
...
...
@@ -41,8 +41,9 @@ public abstract class AbstractMicaProcessor extends AbstractProcessor {
/**
* AutoService 注解处理器
*
* @param annotations 注解 getSupportedAnnotationTypes
* @param roundEnv 扫描到的 注解新
* @param roundEnv
扫描到的 注解新
* @return 是否完成
*/
@Override
...
...
@@ -57,12 +58,118 @@ public abstract class AbstractMicaProcessor extends AbstractProcessor {
protected
abstract
boolean
processImpl
(
Set
<?
extends
TypeElement
>
annotations
,
RoundEnvironment
roundEnv
);
/**
* 判断为类
*
* @param e Element
* @return {boolean}
*/
protected
boolean
isClass
(
Element
e
)
{
ElementKind
kind
=
e
.
getKind
();
return
kind
==
ElementKind
.
CLASS
;
}
/**
* 判断为类或者接口
*
* @param e Element
* @return {boolean}
*/
protected
boolean
isClassOrInterface
(
Element
e
)
{
ElementKind
kind
=
e
.
getKind
();
return
kind
==
ElementKind
.
CLASS
||
kind
==
ElementKind
.
INTERFACE
;
}
/**
* 获取注解,支持组合注解
*
* @param elementUtils elementUtils
* @param e Element
* @param annotationFullName annotationFullName
* @return {boolean}
*/
protected
AnnotationMirror
getAnnotation
(
Elements
elementUtils
,
Element
e
,
String
annotationFullName
)
{
List
<?
extends
AnnotationMirror
>
annotationList
=
elementUtils
.
getAllAnnotationMirrors
(
e
);
for
(
AnnotationMirror
annotation
:
annotationList
)
{
// 如果是对于的注解
if
(
isAnnotation
(
annotationFullName
,
annotation
))
{
return
annotation
;
}
// 处理组合注解
Element
element
=
annotation
.
getAnnotationType
().
asElement
();
// 如果是 java 元注解,继续循环
if
(
element
.
toString
().
startsWith
(
"java.lang"
))
{
continue
;
}
// 递归处理 组合注解
return
getAnnotation
(
elementUtils
,
element
,
annotationFullName
);
}
return
null
;
}
/**
* 判断是相同的注解,支持组合注解
*
* @param elementUtils elementUtils
* @param e Element
* @param annotationFullName annotationFullName
* @return {boolean}
*/
protected
boolean
isAnnotation
(
Elements
elementUtils
,
Element
e
,
String
annotationFullName
)
{
List
<?
extends
AnnotationMirror
>
annotationList
=
elementUtils
.
getAllAnnotationMirrors
(
e
);
for
(
AnnotationMirror
annotation
:
annotationList
)
{
// 如果是对于的注解
if
(
isAnnotation
(
annotationFullName
,
annotation
))
{
return
true
;
}
// 处理组合注解
Element
element
=
annotation
.
getAnnotationType
().
asElement
();
// 如果是 java 元注解,继续循环
if
(
element
.
toString
().
startsWith
(
"java.lang"
))
{
continue
;
}
// 递归处理 组合注解
if
(
isAnnotation
(
elementUtils
,
element
,
annotationFullName
))
{
return
true
;
}
}
return
false
;
}
/**
* 判断是否同一个注解
*
* @param annotationFullName annotationFullName
* @param annotation AnnotationMirror
* @return {boolean}
*/
protected
boolean
isAnnotation
(
String
annotationFullName
,
AnnotationMirror
annotation
)
{
return
annotationFullName
.
equals
(
annotation
.
getAnnotationType
().
toString
());
}
/**
* 获取属性的名称
*
* @param element Element
* @return {String}
*/
protected
String
getQualifiedName
(
Element
element
)
{
if
(
element
instanceof
QualifiedNameable
)
{
return
((
QualifiedNameable
)
element
).
getQualifiedName
().
toString
();
}
return
element
.
toString
();
}
protected
void
log
(
String
msg
)
{
if
(
processingEnv
.
getOptions
().
containsKey
(
"debug"
))
{
processingEnv
.
getMessager
().
printMessage
(
Kind
.
NOTE
,
msg
);
}
}
protected
void
error
(
String
msg
,
Element
element
)
{
processingEnv
.
getMessager
().
printMessage
(
Kind
.
ERROR
,
msg
,
element
);
}
protected
void
error
(
String
msg
,
Element
element
,
AnnotationMirror
annotation
)
{
processingEnv
.
getMessager
().
printMessage
(
Kind
.
ERROR
,
msg
,
element
,
annotation
);
}
...
...
src/main/java/net/dreamlu/mica/auto/common/BootAutoType.java
浏览文件 @
6017ad41
...
...
@@ -16,8 +16,8 @@
package
net.dreamlu.mica.auto.common
;
import
lombok.AllArgsConstructor
;
import
lombok.Getter
;
import
lombok.RequiredArgsConstructor
;
import
net.dreamlu.mica.auto.annotation.AutoContextInitializer
;
import
net.dreamlu.mica.auto.annotation.AutoFailureAnalyzer
;
import
net.dreamlu.mica.auto.annotation.AutoListener
;
...
...
@@ -28,7 +28,7 @@ import net.dreamlu.mica.auto.annotation.AutoListener;
* @author L.cm
*/
@Getter
@
All
ArgsConstructor
@
Required
ArgsConstructor
public
enum
BootAutoType
{
/**
* 注解处理的类型
...
...
src/main/java/net/dreamlu/mica/auto/factories/AutoFactoriesProcessor.java
浏览文件 @
6017ad41
...
...
@@ -22,7 +22,6 @@ import net.dreamlu.mica.auto.common.BootAutoType;
import
net.dreamlu.mica.auto.common.MultiSetMap
;
import
javax.annotation.processing.*
;
import
javax.lang.model.element.AnnotationMirror
;
import
javax.lang.model.element.Element
;
import
javax.lang.model.element.ElementKind
;
import
javax.lang.model.element.TypeElement
;
...
...
@@ -34,7 +33,6 @@ import java.net.URI;
import
java.net.URISyntaxException
;
import
java.nio.file.Path
;
import
java.nio.file.Paths
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.stream.Collectors
;
...
...
@@ -163,34 +161,4 @@ public class AutoFactoriesProcessor extends AbstractMicaProcessor {
fatalError
(
e
);
}
}
private
boolean
isClassOrInterface
(
Element
e
)
{
ElementKind
kind
=
e
.
getKind
();
return
kind
==
ElementKind
.
CLASS
||
kind
==
ElementKind
.
INTERFACE
;
}
private
boolean
isAnnotation
(
Elements
elementUtils
,
Element
e
,
String
annotationFullName
)
{
List
<?
extends
AnnotationMirror
>
annotationList
=
elementUtils
.
getAllAnnotationMirrors
(
e
);
for
(
AnnotationMirror
annotation
:
annotationList
)
{
// 如果是对于的注解
if
(
isAnnotation
(
annotationFullName
,
annotation
))
{
return
true
;
}
// 处理组合注解
Element
element
=
annotation
.
getAnnotationType
().
asElement
();
// 如果是 java 元注解,继续循环
if
(
element
.
toString
().
startsWith
(
"java.lang"
))
{
continue
;
}
// 递归处理 组合注解
if
(
isAnnotation
(
elementUtils
,
element
,
annotationFullName
))
{
return
true
;
}
}
return
false
;
}
private
boolean
isAnnotation
(
String
annotationFullName
,
AnnotationMirror
annotation
)
{
return
annotationFullName
.
equals
(
annotation
.
getAnnotationType
().
toString
());
}
}
src/main/java/net/dreamlu/mica/auto/service/AutoServiceProcessor.java
0 → 100644
浏览文件 @
6017ad41
/*
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
net.dreamlu.mica.auto.service
;
import
com.google.auto.service.AutoService
;
import
net.dreamlu.mica.auto.common.AbstractMicaProcessor
;
import
net.dreamlu.mica.auto.common.MultiSetMap
;
import
javax.annotation.processing.*
;
import
javax.lang.model.element.*
;
import
javax.lang.model.type.DeclaredType
;
import
javax.lang.model.type.TypeMirror
;
import
javax.lang.model.util.Elements
;
import
javax.lang.model.util.SimpleAnnotationValueVisitor8
;
import
javax.lang.model.util.Types
;
import
javax.tools.FileObject
;
import
javax.tools.StandardLocation
;
import
java.io.IOException
;
import
java.io.OutputStream
;
import
java.util.*
;
import
java.util.stream.Collectors
;
/**
* java spi 服务自动处理器 参考:google auto
*
* @author L.cm
*/
@SupportedOptions
(
"debug"
)
@AutoService
(
Processor
.
class
)
public
class
AutoServiceProcessor
extends
AbstractMicaProcessor
{
/**
* AutoService 注解名
*/
private
static
final
String
AUTO_SERVICE_NAME
=
net
.
dreamlu
.
mica
.
auto
.
annotation
.
AutoService
.
class
.
getName
();
/**
* spi 服务集合,key 接口 -> value 实现列表
*/
private
MultiSetMap
<
String
,
String
>
providers
=
new
MultiSetMap
<>();
/**
* 元素辅助类
*/
private
Elements
elementUtils
;
@Override
public
synchronized
void
init
(
ProcessingEnvironment
processingEnv
)
{
super
.
init
(
processingEnv
);
elementUtils
=
processingEnv
.
getElementUtils
();
}
@Override
public
Set
<
String
>
getSupportedAnnotationTypes
()
{
return
Collections
.
singleton
(
AUTO_SERVICE_NAME
);
}
@Override
protected
boolean
processImpl
(
Set
<?
extends
TypeElement
>
annotations
,
RoundEnvironment
roundEnv
)
{
if
(
roundEnv
.
processingOver
())
{
generateConfigFiles
();
}
else
{
processAnnotations
(
annotations
,
roundEnv
);
}
return
false
;
}
private
void
processAnnotations
(
Set
<?
extends
TypeElement
>
annotations
,
RoundEnvironment
roundEnv
)
{
TypeElement
autoService
=
elementUtils
.
getTypeElement
(
AUTO_SERVICE_NAME
);
Set
<?
extends
Element
>
elementSet
=
roundEnv
.
getElementsAnnotatedWith
(
autoService
);
// 过滤 TypeElement
Set
<
TypeElement
>
typeElementSet
=
elementSet
.
stream
()
.
filter
(
this
::
isClass
)
.
filter
(
e
->
e
instanceof
TypeElement
)
.
map
(
e
->
(
TypeElement
)
e
)
.
collect
(
Collectors
.
toSet
());
// 如果为空直接跳出
if
(
typeElementSet
.
isEmpty
())
{
log
(
"Annotations elementSet is isEmpty"
);
return
;
}
log
(
annotations
.
toString
());
log
(
typeElementSet
.
toString
());
for
(
TypeElement
typeElement
:
typeElementSet
)
{
AnnotationMirror
annotationMirror
=
getAnnotation
(
elementUtils
,
typeElement
,
AUTO_SERVICE_NAME
);
if
(
annotationMirror
==
null
)
{
continue
;
}
Set
<
TypeMirror
>
typeMirrors
=
getValueFieldOfClasses
(
annotationMirror
);
if
(
typeMirrors
.
isEmpty
())
{
error
(
"No service interfaces provided for element!"
,
typeElement
,
annotationMirror
);
continue
;
}
// 接口的名称
String
providerImplementerName
=
getQualifiedName
(
typeElement
);
for
(
TypeMirror
typeMirror
:
typeMirrors
)
{
String
providerInterfaceName
=
getType
(
typeMirror
);
log
(
"provider interface: "
+
providerInterfaceName
);
log
(
"provider implementer: "
+
providerImplementerName
);
if
(
checkImplementer
(
typeElement
,
typeMirror
))
{
providers
.
put
(
providerInterfaceName
,
getQualifiedName
(
typeElement
));
}
else
{
String
message
=
"ServiceProviders must implement their service provider interface. "
+
providerImplementerName
+
" does not implement "
+
providerInterfaceName
;
error
(
message
,
typeElement
,
annotationMirror
);
}
}
}
}
private
void
generateConfigFiles
()
{
Filer
filer
=
processingEnv
.
getFiler
();
for
(
String
providerInterface
:
providers
.
keySet
())
{
String
resourceFile
=
"META-INF/services/"
+
providerInterface
;
log
(
"Working on resource file: "
+
resourceFile
);
try
{
SortedSet
<
String
>
allServices
=
new
TreeSet
<>();
try
{
FileObject
existingFile
=
filer
.
getResource
(
StandardLocation
.
CLASS_OUTPUT
,
""
,
resourceFile
);
log
(
"Looking for existing resource file at "
+
existingFile
.
toUri
());
Set
<
String
>
oldServices
=
ServicesFiles
.
readServiceFile
(
existingFile
.
openInputStream
());
log
(
"Existing service entries: "
+
oldServices
);
allServices
.
addAll
(
oldServices
);
}
catch
(
IOException
e
)
{
log
(
"Resource file did not already exist."
);
}
Set
<
String
>
newServices
=
new
HashSet
<>(
providers
.
get
(
providerInterface
));
if
(
allServices
.
containsAll
(
newServices
))
{
log
(
"No new service entries being added."
);
return
;
}
allServices
.
addAll
(
newServices
);
log
(
"New service file contents: "
+
allServices
);
FileObject
fileObject
=
filer
.
createResource
(
StandardLocation
.
CLASS_OUTPUT
,
""
,
resourceFile
);
OutputStream
out
=
fileObject
.
openOutputStream
();
ServicesFiles
.
writeServiceFile
(
allServices
,
out
);
out
.
close
();
log
(
"Wrote to: "
+
fileObject
.
toUri
());
}
catch
(
IOException
e
)
{
fatalError
(
"Unable to create "
+
resourceFile
+
", "
+
e
);
return
;
}
}
}
/**
* Verifies {@link java.util.spi.LocaleServiceProvider} constraints on the concrete provider class.
* Note that these constraints are enforced at runtime via the ServiceLoader,
* we're just checking them at compile time to be extra nice to our users.
*/
private
boolean
checkImplementer
(
Element
providerImplementer
,
TypeMirror
providerType
)
{
// TODO: We're currently only enforcing the subtype relationship
// constraint. It would be nice to enforce them all.
Types
types
=
processingEnv
.
getTypeUtils
();
return
types
.
isSubtype
(
providerImplementer
.
asType
(),
providerType
);
}
/**
* 读取 AutoService 上的 value 值
*
* @param annotationMirror AnnotationMirror
* @return value 集合
*/
private
Set
<
TypeMirror
>
getValueFieldOfClasses
(
AnnotationMirror
annotationMirror
)
{
return
getAnnotationValue
(
annotationMirror
,
"value"
)
.
accept
(
new
SimpleAnnotationValueVisitor8
<
Set
<
TypeMirror
>,
Void
>()
{
@Override
public
Set
<
TypeMirror
>
visitType
(
TypeMirror
typeMirror
,
Void
v
)
{
return
Collections
.
singleton
(
typeMirror
);
}
@Override
public
Set
<
TypeMirror
>
visitArray
(
List
<?
extends
AnnotationValue
>
values
,
Void
v
)
{
return
values
.
stream
()
.
flatMap
(
value
->
value
.
accept
(
this
,
null
).
stream
())
.
collect
(
Collectors
.
toSet
());
}
},
null
);
}
public
AnnotationValue
getAnnotationValue
(
AnnotationMirror
annotationMirror
,
String
elementName
)
{
Objects
.
requireNonNull
(
annotationMirror
);
Objects
.
requireNonNull
(
elementName
);
for
(
Map
.
Entry
<?
extends
ExecutableElement
,
?
extends
AnnotationValue
>
entry
:
elementUtils
.
getElementValuesWithDefaults
(
annotationMirror
).
entrySet
())
{
if
(
entry
.
getKey
().
getSimpleName
().
contentEquals
(
elementName
))
{
return
entry
.
getValue
();
}
}
String
annotationName
=
annotationMirror
.
getAnnotationType
().
toString
();
throw
new
IllegalArgumentException
(
String
.
format
(
"@%s does not define an element %s()"
,
annotationName
,
elementName
));
}
public
String
getType
(
TypeMirror
type
)
{
if
(
type
==
null
)
{
return
null
;
}
if
(
type
instanceof
DeclaredType
)
{
DeclaredType
declaredType
=
(
DeclaredType
)
type
;
Element
enclosingElement
=
declaredType
.
asElement
().
getEnclosingElement
();
if
(
enclosingElement
!=
null
&&
enclosingElement
instanceof
TypeElement
)
{
return
getQualifiedName
(
enclosingElement
)
+
"$"
+
declaredType
.
asElement
().
getSimpleName
().
toString
();
}
else
{
return
getQualifiedName
(
declaredType
.
asElement
());
}
}
return
type
.
toString
();
}
}
src/main/java/net/dreamlu/mica/auto/service/ServicesFiles.java
0 → 100644
浏览文件 @
6017ad41
/*
* Copyright (c) 2019-2029, Dreamlu 卢春梦 (596392912@qq.com & www.dreamlu.net).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package
net.dreamlu.mica.auto.service
;
import
lombok.experimental.UtilityClass
;
import
java.io.*
;
import
java.nio.charset.Charset
;
import
java.nio.charset.StandardCharsets
;
import
java.util.Collection
;
import
java.util.HashSet
;
import
java.util.Set
;
/**
* A helper class for reading and writing Services files.
*
* @author L.cm
*/
@UtilityClass
class
ServicesFiles
{
private
static
final
Charset
UTF_8
=
StandardCharsets
.
UTF_8
;
/**
* Reads the set of service classes from a service file.
*
* @param input not {@code null}. Closed after use.
* @return a not {@code null Set} of service class names.
* @throws IOException
*/
static
Set
<
String
>
readServiceFile
(
InputStream
input
)
throws
IOException
{
HashSet
<
String
>
serviceClasses
=
new
HashSet
<>();
try
(
InputStreamReader
isr
=
new
InputStreamReader
(
input
,
UTF_8
);
BufferedReader
r
=
new
BufferedReader
(
isr
)
)
{
String
line
;
while
((
line
=
r
.
readLine
())
!=
null
)
{
int
commentStart
=
line
.
indexOf
(
'#'
);
if
(
commentStart
>=
0
)
{
line
=
line
.
substring
(
0
,
commentStart
);
}
line
=
line
.
trim
();
if
(!
line
.
isEmpty
())
{
serviceClasses
.
add
(
line
);
}
}
return
serviceClasses
;
}
}
/**
* Writes the set of service class names to a service file.
*
* @param output not {@code null}. Not closed after use.
* @param services a not {@code null Collection} of service class names.
* @throws IOException
*/
static
void
writeServiceFile
(
Collection
<
String
>
services
,
OutputStream
output
)
throws
IOException
{
BufferedWriter
writer
=
new
BufferedWriter
(
new
OutputStreamWriter
(
output
,
UTF_8
));
for
(
String
service
:
services
)
{
writer
.
write
(
service
);
writer
.
newLine
();
}
writer
.
flush
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录