Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xxadev
jenkins
提交
8d150d57
J
jenkins
项目概览
xxadev
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
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,发现更多精彩内容 >>
提交
8d150d57
编写于
12月 15, 2010
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
pushing ItemGroupParent implementations outside to facilitate different implemenations.
上级
43c17872
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
213 addition
and
120 deletion
+213
-120
core/src/main/java/hudson/model/Hudson.java
core/src/main/java/hudson/model/Hudson.java
+20
-114
core/src/main/java/hudson/model/ItemGroupMixIn.java
core/src/main/java/hudson/model/ItemGroupMixIn.java
+185
-3
core/src/main/java/hudson/model/Items.java
core/src/main/java/hudson/model/Items.java
+4
-2
core/src/main/java/hudson/model/TopLevelItem.java
core/src/main/java/hudson/model/TopLevelItem.java
+4
-1
未找到文件。
core/src/main/java/hudson/model/Hudson.java
浏览文件 @
8d150d57
...
...
@@ -126,7 +126,6 @@ import hudson.util.TextFile;
import
hudson.util.VersionNumber
;
import
hudson.util.XStream2
;
import
hudson.util.Service
;
import
hudson.util.IOUtils
;
import
hudson.views.DefaultMyViewsTabBar
;
import
hudson.views.DefaultViewsTabBar
;
import
hudson.views.MyViewsTabBar
;
...
...
@@ -155,7 +154,6 @@ import org.jvnet.hudson.reactor.ReactorListener;
import
org.jvnet.hudson.reactor.TaskGraphBuilder.Handle
;
import
org.kohsuke.args4j.Argument
;
import
org.kohsuke.args4j.Option
;
import
org.kohsuke.stapler.Ancestor
;
import
org.kohsuke.stapler.HttpRedirect
;
import
org.kohsuke.stapler.HttpResponse
;
import
org.kohsuke.stapler.HttpResponses
;
...
...
@@ -539,6 +537,21 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*/
private
transient
final
AdjunctManager
adjuncts
;
/**
* Code that handles {@link ItemGroup} work.
*/
private
transient
final
ItemGroupMixIn
itemGroupMixIn
=
new
ItemGroupMixIn
(
this
,
this
)
{
@Override
protected
void
add
(
TopLevelItem
item
)
{
items
.
put
(
item
.
getName
(),
item
);
}
@Override
protected
File
getRootDirFor
(
String
name
)
{
return
Hudson
.
this
.
getRootDirFor
(
name
);
}
};
@CLIResolver
public
static
Hudson
getInstance
()
{
return
theInstance
;
...
...
@@ -2085,25 +2098,8 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* @throws IllegalArgumentException
* if a project of the give name already exists.
*/
public
synchronized
TopLevelItem
createProject
(
TopLevelItemDescriptor
type
,
String
name
,
boolean
notify
)
throws
IOException
{
if
(
items
.
containsKey
(
name
))
throw
new
IllegalArgumentException
(
"Project of the name "
+
name
+
" already exists"
);
TopLevelItem
item
;
try
{
item
=
type
.
newInstance
(
name
);
}
catch
(
Exception
e
)
{
throw
new
IllegalArgumentException
(
e
);
}
item
.
onCreatedFromScratch
();
item
.
save
();
items
.
put
(
name
,
item
);
if
(
notify
)
ItemListener
.
fireOnCreated
(
item
);
return
item
;
public
synchronized
TopLevelItem
createProject
(
TopLevelItemDescriptor
type
,
String
name
,
boolean
notify
)
throws
IOException
{
return
itemGroupMixIn
.
createProject
(
type
,
name
,
notify
);
}
/**
...
...
@@ -2613,67 +2609,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
}
public
synchronized
Item
doCreateItem
(
StaplerRequest
req
,
StaplerResponse
rsp
)
throws
IOException
,
ServletException
{
checkPermission
(
Job
.
CREATE
);
TopLevelItem
result
;
String
requestContentType
=
req
.
getContentType
();
if
(
requestContentType
==
null
)
{
rsp
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"No Content-Type header set"
);
return
null
;
}
boolean
isXmlSubmission
=
requestContentType
.
startsWith
(
"application/xml"
)
||
requestContentType
.
startsWith
(
"text/xml"
);
String
name
=
req
.
getParameter
(
"name"
);
if
(
name
==
null
)
{
rsp
.
sendError
(
HttpServletResponse
.
SC_BAD_REQUEST
,
"Query parameter 'name' is required"
);
return
null
;
}
name
=
checkJobName
(
name
);
String
mode
=
req
.
getParameter
(
"mode"
);
if
(
mode
!=
null
&&
mode
.
equals
(
"copy"
))
{
String
from
=
req
.
getParameter
(
"from"
);
TopLevelItem
src
=
getItem
(
from
);
if
(
src
==
null
)
{
rsp
.
setStatus
(
SC_BAD_REQUEST
);
if
(
Util
.
fixEmpty
(
from
)==
null
)
sendError
(
"Specify which job to copy"
,
req
,
rsp
);
else
sendError
(
"No such job: "
+
from
,
req
,
rsp
);
return
null
;
}
result
=
copy
(
src
,
name
);
}
else
{
if
(
isXmlSubmission
)
{
result
=
createProjectFromXML
(
name
,
req
.
getInputStream
());
rsp
.
setStatus
(
HttpServletResponse
.
SC_OK
);
return
result
;
}
else
{
if
(
mode
==
null
)
{
rsp
.
sendError
(
SC_BAD_REQUEST
);
return
null
;
}
// create empty job and redirect to the project config screen
result
=
createProject
(
Items
.
getDescriptor
(
mode
),
name
);
}
}
// send the browser to the config page
// use View to trim view/{default-view} from URL if possible
String
redirect
=
result
.
getUrl
()+
"configure"
;
List
<
Ancestor
>
ancestors
=
req
.
getAncestors
();
for
(
int
i
=
ancestors
.
size
()
-
1
;
i
>=
0
;
i
--)
{
Object
o
=
ancestors
.
get
(
i
).
getObject
();
if
(
o
instanceof
View
)
{
redirect
=
req
.
getContextPath
()
+
'/'
+
((
View
)
o
).
getUrl
()
+
redirect
;
break
;
}
}
rsp
.
sendRedirect2
(
redirect
);
return
result
;
return
itemGroupMixIn
.
createTopLevelItem
(
req
,
rsp
);
}
/**
...
...
@@ -2682,25 +2618,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* @since 1.319
*/
public
TopLevelItem
createProjectFromXML
(
String
name
,
InputStream
xml
)
throws
IOException
{
// place it as config.xml
File
configXml
=
Items
.
getConfigFile
(
getRootDirFor
(
name
)).
getFile
();
configXml
.
getParentFile
().
mkdirs
();
try
{
IOUtils
.
copy
(
xml
,
configXml
);
// load it
TopLevelItem
result
=
(
TopLevelItem
)
Items
.
load
(
this
,
configXml
.
getParentFile
());
items
.
put
(
name
,
result
);
ItemListener
.
fireOnCreated
(
result
);
rebuildDependencyGraph
();
return
result
;
}
catch
(
IOException
e
)
{
// if anything fails, delete the config file to avoid further confusion
Util
.
deleteRecursive
(
configXml
.
getParentFile
());
throw
e
;
}
return
itemGroupMixIn
.
createProjectFromXML
(
name
,
xml
);
}
/**
...
...
@@ -2715,19 +2633,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*/
@SuppressWarnings
({
"unchecked"
})
public
<
T
extends
TopLevelItem
>
T
copy
(
T
src
,
String
name
)
throws
IOException
{
T
result
=
(
T
)
createProject
(
src
.
getDescriptor
(),
name
,
false
);
// copy config
Util
.
copyFile
(
Items
.
getConfigFile
(
src
).
getFile
(),
Items
.
getConfigFile
(
result
).
getFile
());
// reload from the new config
result
=
(
T
)
Items
.
load
(
this
,
result
.
getRootDir
());
result
.
onCopiedFrom
(
src
);
items
.
put
(
name
,
result
);
ItemListener
.
fireOnCopied
(
src
,
result
);
return
result
;
return
itemGroupMixIn
.
copy
(
src
,
name
);
}
// a little more convenient overloading that assumes the caller gives us the right type
...
...
core/src/main/java/hudson/model/ItemGroupMixIn.java
浏览文件 @
8d150d57
/*
* The MIT License
*
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
* Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi
, CloudBees, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
...
...
@@ -23,21 +23,62 @@
*/
package
hudson.model
;
import
hudson.Util
;
import
hudson.model.listeners.ItemListener
;
import
hudson.security.AccessControlled
;
import
hudson.util.CopyOnWriteMap
;
import
hudson.util.Function1
;
import
hudson.util.IOUtils
;
import
org.kohsuke.stapler.Ancestor
;
import
org.kohsuke.stapler.StaplerRequest
;
import
org.kohsuke.stapler.StaplerResponse
;
import
javax.servlet.ServletException
;
import
javax.servlet.http.HttpServletResponse
;
import
java.io.File
;
import
java.io.FileFilter
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.util.List
;
import
java.util.Map
;
/**
* Defines a bunch of static methods to be used as a "mix-in" for {@link ItemGroup}
* implementations.
* implementations.
Not meant for a consumption from outside {@link ItemGroup}s.
*
* @author Kohsuke Kawaguchi
*/
public
class
ItemGroupMixIn
{
public
abstract
class
ItemGroupMixIn
{
/**
* {@link ItemGroup} for which we are working.
*/
private
final
ItemGroup
parent
;
private
final
AccessControlled
acl
;
protected
ItemGroupMixIn
(
ItemGroup
parent
,
AccessControlled
acl
)
{
this
.
parent
=
parent
;
this
.
acl
=
acl
;
}
/*
* Callback methods to be implemented by the ItemGroup implementation.
*/
/**
* Adds a newly created item to the parent.
*/
protected
abstract
void
add
(
TopLevelItem
item
);
/**
* Assigns the root directory for a prospective item.
*/
protected
abstract
File
getRootDirFor
(
String
name
);
/*
* The rest is the methods that provide meat.
*/
/**
* Loads all the child {@link Item}s.
*
...
...
@@ -73,4 +114,145 @@ public class ItemGroupMixIn {
return
item
.
getName
();
}
};
/**
* Creates a {@link TopLevelItem} from the submission of the '/lib/hudson/newFromList/formList'
*/
public
synchronized
TopLevelItem
createTopLevelItem
(
StaplerRequest
req
,
StaplerResponse
rsp
)
throws
IOException
,
ServletException
{
acl
.
checkPermission
(
Job
.
CREATE
);
TopLevelItem
result
;
String
requestContentType
=
req
.
getContentType
();
if
(
requestContentType
==
null
)
throw
new
Failure
(
"No Content-Type header set"
);
boolean
isXmlSubmission
=
requestContentType
.
startsWith
(
"application/xml"
)
||
requestContentType
.
startsWith
(
"text/xml"
);
String
name
=
req
.
getParameter
(
"name"
);
if
(
name
==
null
)
throw
new
Failure
(
"Query parameter 'name' is required"
);
{
// check if the name looks good
Hudson
.
checkGoodName
(
name
);
name
=
name
.
trim
();
if
(
parent
.
getItem
(
name
)!=
null
)
throw
new
Failure
(
Messages
.
Hudson_JobAlreadyExists
(
name
));
}
String
mode
=
req
.
getParameter
(
"mode"
);
if
(
mode
!=
null
&&
mode
.
equals
(
"copy"
))
{
String
from
=
req
.
getParameter
(
"from"
);
Item
src
=
parent
.
getItem
(
from
);
if
(
src
==
null
)
{
if
(
Util
.
fixEmpty
(
from
)==
null
)
throw
new
Failure
(
"Specify which job to copy"
);
else
throw
new
Failure
(
"No such job: "
+
from
);
}
if
(!(
src
instanceof
TopLevelItem
))
{
throw
new
Failure
(
from
+
" cannot be copied"
);
}
result
=
copy
((
TopLevelItem
)
src
,
name
);
}
else
{
if
(
isXmlSubmission
)
{
result
=
createProjectFromXML
(
name
,
req
.
getInputStream
());
rsp
.
setStatus
(
HttpServletResponse
.
SC_OK
);
return
result
;
}
else
{
if
(
mode
==
null
)
throw
new
Failure
(
"No mode given"
);
// create empty job and redirect to the project config screen
result
=
createProject
(
Items
.
getDescriptor
(
mode
),
name
,
true
);
}
}
// send the browser to the config page
// use View to trim view/{default-view} from URL if possible
String
redirect
=
result
.
getUrl
()+
"configure"
;
List
<
Ancestor
>
ancestors
=
req
.
getAncestors
();
for
(
int
i
=
ancestors
.
size
()
-
1
;
i
>=
0
;
i
--)
{
Object
o
=
ancestors
.
get
(
i
).
getObject
();
if
(
o
instanceof
View
)
{
redirect
=
req
.
getContextPath
()
+
'/'
+
((
View
)
o
).
getUrl
()
+
redirect
;
break
;
}
}
rsp
.
sendRedirect2
(
redirect
);
return
result
;
}
/**
* Copies an existing {@link TopLevelItem} to a new name.
*
* The caller is responsible for calling {@link ItemListener#fireOnCopied(Item, Item)}. This method
* cannot do that because it doesn't know how to make the newly added item reachable from the parent.
*/
@SuppressWarnings
({
"unchecked"
})
public
synchronized
<
T
extends
TopLevelItem
>
T
copy
(
T
src
,
String
name
)
throws
IOException
{
acl
.
checkPermission
(
Job
.
CREATE
);
T
result
=
(
T
)
createProject
(
src
.
getDescriptor
(),
name
,
false
);
// copy config
Util
.
copyFile
(
Items
.
getConfigFile
(
src
).
getFile
(),
Items
.
getConfigFile
(
result
).
getFile
());
// reload from the new config
result
=
(
T
)
Items
.
load
(
parent
,
result
.
getRootDir
());
result
.
onCopiedFrom
(
src
);
add
(
result
);
ItemListener
.
fireOnCopied
(
src
,
result
);
return
result
;
}
public
synchronized
TopLevelItem
createProjectFromXML
(
String
name
,
InputStream
xml
)
throws
IOException
{
acl
.
checkPermission
(
Job
.
CREATE
);
// place it as config.xml
File
configXml
=
Items
.
getConfigFile
(
getRootDirFor
(
name
)).
getFile
();
configXml
.
getParentFile
().
mkdirs
();
try
{
IOUtils
.
copy
(
xml
,
configXml
);
// load it
TopLevelItem
result
=
(
TopLevelItem
)
Items
.
load
(
parent
,
configXml
.
getParentFile
());
add
(
result
);
ItemListener
.
fireOnCreated
(
result
);
Hudson
.
getInstance
().
rebuildDependencyGraph
();
return
result
;
}
catch
(
IOException
e
)
{
// if anything fails, delete the config file to avoid further confusion
Util
.
deleteRecursive
(
configXml
.
getParentFile
());
throw
e
;
}
}
public
synchronized
TopLevelItem
createProject
(
TopLevelItemDescriptor
type
,
String
name
,
boolean
notify
)
throws
IOException
{
acl
.
checkPermission
(
Job
.
CREATE
);
if
(
parent
.
getItem
(
name
)!=
null
)
throw
new
IllegalArgumentException
(
"Project of the name "
+
name
+
" already exists"
);
TopLevelItem
item
;
try
{
item
=
type
.
newInstance
(
parent
,
name
);
}
catch
(
Exception
e
)
{
throw
new
IllegalArgumentException
(
e
);
}
item
.
onCreatedFromScratch
();
item
.
save
();
add
(
item
);
if
(
notify
)
ItemListener
.
fireOnCreated
(
item
);
return
item
;
}
}
core/src/main/java/hudson/model/Items.java
浏览文件 @
8d150d57
...
...
@@ -24,15 +24,17 @@
package
hudson.model
;
import
com.thoughtworks.xstream.XStream
;
import
hudson.XmlFile
;
import
hudson.DescriptorExtensionList
;
import
hudson.Extension
;
import
hudson.scm.RepositoryBrowser
;
import
hudson.matrix.MatrixProject
;
import
hudson.matrix.MatrixConfiguration
;
import
hudson.XmlFile
;
import
hudson.matrix.Axis
;
import
hudson.util.XStream2
;
import
hudson.matrix.MatrixConfiguration
;
import
hudson.matrix.MatrixProject
;
import
hudson.util.DescriptorList
;
import
hudson.util.XStream2
;
import
java.io.File
;
import
java.io.IOException
;
...
...
core/src/main/java/hudson/model/TopLevelItem.java
浏览文件 @
8d150d57
...
...
@@ -25,9 +25,12 @@ package hudson.model;
import
hudson.Extension
;
import
hudson.ExtensionPoint
;
import
hudson.matrix.MatrixConfiguration
;
/**
* {@link Item} that can be directly displayed under {@link Hudson}.
* {@link Item} that can be directly displayed under {@link Hudson} or other containers.
* Ones that don't need to be under specific parent (say, unlike {@link MatrixConfiguration}),
* and thus can be freely moved, copied, etc.
*
* <p>
* To register a custom {@link TopLevelItem} class from a plugin, put {@link Extension} on your
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录