Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
LinuxSuRen
jenkins
提交
5d903514
J
jenkins
项目概览
LinuxSuRen
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
5d903514
编写于
9月 23, 2011
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
improve error recovery behaviour
上级
81d525b3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
115 addition
and
97 deletion
+115
-97
core/src/main/java/hudson/ExtensionFinder.java
core/src/main/java/hudson/ExtensionFinder.java
+95
-50
core/src/main/java/jenkins/OptionalComponentValidator.java
core/src/main/java/jenkins/OptionalComponentValidator.java
+0
-47
test/src/test/java/hudson/ExtensionFinderTest.java
test/src/test/java/hudson/ExtensionFinderTest.java
+20
-0
未找到文件。
core/src/main/java/hudson/ExtensionFinder.java
浏览文件 @
5d903514
...
...
@@ -25,6 +25,7 @@ package hudson;
import
com.google.inject.AbstractModule
;
import
com.google.inject.Binding
;
import
com.google.inject.CreationException
;
import
com.google.inject.Guice
;
import
com.google.inject.Injector
;
import
com.google.inject.Key
;
...
...
@@ -169,61 +170,20 @@ public abstract class ExtensionFinder implements ExtensionPoint {
public
AbstractGuiceFinder
(
final
Class
<
T
>
annotationType
)
{
List
<
Module
>
modules
=
new
ArrayList
<
Module
>();
modules
.
add
(
new
AbstractModule
()
{
@SuppressWarnings
({
"unchecked"
,
"ChainOfInstanceofChecks"
})
@Override
protected
void
configure
()
{
ClassLoader
cl
=
Hudson
.
getInstance
().
getPluginManager
().
uberClassLoader
;
int
id
=
0
;
for
(
final
IndexItem
<
T
,
Object
>
item
:
Index
.
load
(
annotationType
,
Object
.
class
,
cl
))
{
id
++;
try
{
AnnotatedElement
e
=
item
.
element
();
if
(!
isActive
(
e
))
continue
;
T
a
=
item
.
annotation
();
if
(
e
instanceof
Class
)
{
Key
key
=
Key
.
get
((
Class
)
e
);
annotations
.
put
(
key
,
a
);
bind
(
key
).
in
(
FAULT_TOLERANT_SCOPE
);
}
else
{
Class
extType
;
if
(
e
instanceof
Field
)
{
extType
=
((
Field
)
e
).
getType
();
}
else
if
(
e
instanceof
Method
)
{
extType
=
((
Method
)
e
).
getReturnType
();
}
else
throw
new
AssertionError
();
// use arbitrary id to make unique key, because Guice wants that.
Key
key
=
Key
.
get
(
extType
,
Names
.
named
(
String
.
valueOf
(
id
)));
annotations
.
put
(
key
,
a
);
bind
(
key
).
toProvider
(
new
Provider
()
{
public
Object
get
()
{
return
instantiate
(
item
);
}
}).
in
(
FAULT_TOLERANT_SCOPE
);
}
}
catch
(
LinkageError
e
)
{
// sometimes the instantiation fails in an indirect classloading failure,
// which results in a LinkageError
LOGGER
.
log
(
isOptional
(
item
.
annotation
())
?
Level
.
FINE
:
Level
.
WARNING
,
"Failed to load "
+
item
.
className
(),
e
);
}
catch
(
InstantiationException
e
)
{
LOGGER
.
log
(
isOptional
(
item
.
annotation
())
?
Level
.
FINE
:
Level
.
WARNING
,
"Failed to load "
+
item
.
className
(),
e
);
}
}
}
});
modules
.
add
(
new
SezpozModule
(
annotationType
,
Jenkins
.
getInstance
().
getPluginManager
().
uberClassLoader
));
for
(
ExtensionComponent
<
Module
>
ec
:
new
Sezpoz
().
find
(
Module
.
class
,
Hudson
.
getInstance
()))
{
modules
.
add
(
ec
.
getInstance
());
}
container
=
Guice
.
createInjector
(
modules
);
try
{
container
=
Guice
.
createInjector
(
modules
);
}
catch
(
CreationException
e
)
{
LOGGER
.
log
(
Level
.
SEVERE
,
"Failed to create Guice container from all the plugins"
,
e
);
// failing to load all bindings are disastrous, so recover by creating minimum that works
// by just including the core
container
=
Guice
.
createInjector
(
new
SezpozModule
(
annotationType
,
Jenkins
.
class
.
getClassLoader
()));
}
}
protected
abstract
double
getOrdinal
(
T
annotation
);
...
...
@@ -300,6 +260,91 @@ public abstract class ExtensionFinder implements ExtensionPoint {
};
private
static
final
Logger
LOGGER
=
Logger
.
getLogger
(
GuiceFinder
.
class
.
getName
());
private
class
SezpozModule
extends
AbstractModule
{
private
final
Class
<
T
>
annotationType
;
private
final
ClassLoader
cl
;
public
SezpozModule
(
Class
<
T
>
annotationType
,
ClassLoader
cl
)
{
this
.
annotationType
=
annotationType
;
this
.
cl
=
cl
;
}
/**
* Guice performs various reflection operations on the class to figure out the dependency graph,
* and that process can cause additional classloading problems, which will fail the injector creation,
* which in turn has disastrous effect on the startup.
*
* <p>
* Ultimately I'd like to isolate problems to plugins and selectively disable them, allowing
* Jenkins to start with plugins that work, but I haven't figured out how.
*
* So this is an attempt to detect subset of problems eagerly, by invoking various reflection
* operations and try to find non-existent classes early.
*/
private
void
resolve
(
Class
c
)
{
try
{
c
.
getGenericSuperclass
();
c
.
getGenericInterfaces
();
ClassLoader
ecl
=
c
.
getClassLoader
();
Method
m
=
ClassLoader
.
class
.
getDeclaredMethod
(
"resolveClass"
,
Class
.
class
);
m
.
setAccessible
(
true
);
m
.
invoke
(
ecl
,
c
);
}
catch
(
Exception
x
)
{
throw
(
LinkageError
)
new
LinkageError
(
"Failed to resolve "
+
c
).
initCause
(
x
);
}
}
@SuppressWarnings
({
"unchecked"
,
"ChainOfInstanceofChecks"
})
@Override
protected
void
configure
()
{
int
id
=
0
;
for
(
final
IndexItem
<
T
,
Object
>
item
:
Index
.
load
(
annotationType
,
Object
.
class
,
cl
))
{
id
++;
try
{
AnnotatedElement
e
=
item
.
element
();
if
(!
isActive
(
e
))
continue
;
T
a
=
item
.
annotation
();
if
(
e
instanceof
Class
)
{
Key
key
=
Key
.
get
((
Class
)
e
);
resolve
((
Class
)
e
);
annotations
.
put
(
key
,
a
);
bind
(
key
).
in
(
FAULT_TOLERANT_SCOPE
);
}
else
{
Class
extType
;
if
(
e
instanceof
Field
)
{
extType
=
((
Field
)
e
).
getType
();
}
else
if
(
e
instanceof
Method
)
{
extType
=
((
Method
)
e
).
getReturnType
();
}
else
throw
new
AssertionError
();
resolve
(
extType
);
// use arbitrary id to make unique key, because Guice wants that.
Key
key
=
Key
.
get
(
extType
,
Names
.
named
(
String
.
valueOf
(
id
)));
annotations
.
put
(
key
,
a
);
bind
(
key
).
toProvider
(
new
Provider
()
{
public
Object
get
()
{
return
instantiate
(
item
);
}
}).
in
(
FAULT_TOLERANT_SCOPE
);
}
}
catch
(
LinkageError
e
)
{
// sometimes the instantiation fails in an indirect classloading failure,
// which results in a LinkageError
LOGGER
.
log
(
isOptional
(
item
.
annotation
())
?
Level
.
FINE
:
Level
.
WARNING
,
"Failed to load "
+
item
.
className
(),
e
);
}
catch
(
InstantiationException
e
)
{
LOGGER
.
log
(
isOptional
(
item
.
annotation
())
?
Level
.
FINE
:
Level
.
WARNING
,
"Failed to load "
+
item
.
className
(),
e
);
}
}
}
}
}
/**
...
...
core/src/main/java/jenkins/OptionalComponentValidator.java
已删除
100644 → 0
浏览文件 @
81d525b3
package
jenkins
;
import
com.google.inject.Binder
;
import
com.google.inject.Binding
;
import
com.google.inject.Module
;
import
com.google.inject.spi.DefaultElementVisitor
;
import
com.google.inject.spi.Dependency
;
import
com.google.inject.spi.Element
;
import
com.google.inject.spi.ElementVisitor
;
import
com.google.inject.spi.Elements
;
import
com.google.inject.spi.HasDependencies
;
import
java.util.Collection
;
/**
* @author Kohsuke Kawaguchi
*/
public
class
OptionalComponentValidator
implements
Module
{
private
final
Collection
<?
extends
Module
>
sources
;
public
OptionalComponentValidator
(
Collection
<?
extends
Module
>
sources
)
{
this
.
sources
=
sources
;
}
public
void
configure
(
final
Binder
binder
)
{
ElementVisitor
<
Boolean
>
visitor
=
new
DefaultElementVisitor
<
Boolean
>()
{
@Override
public
<
T
>
Boolean
visit
(
Binding
<
T
>
binding
)
{
if
(
binding
instanceof
HasDependencies
)
{
for
(
Dependency
d
:
((
HasDependencies
)
binding
).
getDependencies
())
{
}
}
return
true
;
}
@Override
protected
Boolean
visitOther
(
Element
element
)
{
return
true
;
}
};
for
(
Element
e
:
Elements
.
getElements
(
sources
))
{
if
(
e
.
acceptVisitor
(
visitor
))
e
.
applyTo
(
binder
);
}
}
}
test/src/test/java/hudson/ExtensionFinderTest.java
浏览文件 @
5d903514
...
...
@@ -97,4 +97,24 @@ public class ExtensionFinderTest extends HudsonTestCase {
}
}
}
/**
* Tests the error recovery behaviour.
*
* One failure in binding definition shouldn't prevent Jenkins from booting.
*/
public
void
testErrorRecovery
()
{
BrokenExtension
i
=
PageDecorator
.
all
().
get
(
BrokenExtension
.
class
);
assertNull
(
i
);
}
@TestExtension
(
"testErrorRecovery"
)
public
static
class
BrokenExtension
extends
PageDecorator
{
@Inject
Comparable
c
;
public
BrokenExtension
()
{
super
(
InjectingExtension
.
class
);
}
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录