Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
FIY695
jenkins
提交
f527a54a
J
jenkins
项目概览
FIY695
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
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,发现更多精彩内容 >>
提交
f527a54a
编写于
6月 20, 2012
作者:
K
Kohsuke Kawaguchi
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
added data structure useful to capture part of the XStream XML format as a DOM like structure.
上级
b061d3cf
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
507 addition
and
0 deletion
+507
-0
core/src/main/java/jenkins/util/xstream/XStreamDOM.java
core/src/main/java/jenkins/util/xstream/XStreamDOM.java
+414
-0
core/src/test/java/jenkins/util/xstream/XStreamDOMTest.java
core/src/test/java/jenkins/util/xstream/XStreamDOMTest.java
+83
-0
core/src/test/resources/jenkins/util/xstream/XStreamDOMTest.data1.xml
...t/resources/jenkins/util/xstream/XStreamDOMTest.data1.xml
+10
-0
未找到文件。
core/src/main/java/jenkins/util/xstream/XStreamDOM.java
0 → 100644
浏览文件 @
f527a54a
/*
* The MIT License
*
* Copyright (c) 2012, 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.util.xstream
;
import
com.thoughtworks.xstream.XStream
;
import
com.thoughtworks.xstream.converters.Converter
;
import
com.thoughtworks.xstream.converters.ErrorWriter
;
import
com.thoughtworks.xstream.converters.MarshallingContext
;
import
com.thoughtworks.xstream.converters.UnmarshallingContext
;
import
com.thoughtworks.xstream.io.HierarchicalStreamReader
;
import
com.thoughtworks.xstream.io.HierarchicalStreamWriter
;
import
com.thoughtworks.xstream.io.xml.AbstractXmlReader
;
import
com.thoughtworks.xstream.io.xml.AbstractXmlWriter
;
import
com.thoughtworks.xstream.io.xml.DocumentReader
;
import
com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer
;
import
hudson.Util
;
import
java.util.AbstractList
;
import
java.util.ArrayList
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map.Entry
;
import
java.util.Stack
;
/**
* XML DOM like structure to preserve a portion of XStream data as-is, so that you can
* process it later in a separate XStream call.
*
* <p>
* This object captures a subset of XML infoset that XStream understands. Namely, no XML namespace,
* no mixed content.
*
* <p>
* You use it as a field in your class (that itself participates in an XStream persistence),
* and have it receive the portion of that XML. Then later you can use {@link #unmarshal(XStream)}
* to convert this sub-tree to an object with a possibly separate XStream instance.
* <p>
* The reverse operation is {@link #from(XStream, Object)} method, which marshals an object
* into {@link XStreamDOM}.
*
* @author Kohsuke Kawaguchi
* @since 1.473
*/
public
class
XStreamDOM
{
private
final
String
tagName
;
private
final
String
[]
attributes
;
// one of them is non-null, the other is null
private
final
String
value
;
private
final
List
<
XStreamDOM
>
children
;
public
XStreamDOM
(
String
tagName
,
Map
<
String
,
String
>
attributes
,
String
value
)
{
this
.
tagName
=
tagName
;
this
.
attributes
=
toAttributeList
(
attributes
);
this
.
value
=
value
;
this
.
children
=
null
;
}
public
XStreamDOM
(
String
tagName
,
Map
<
String
,
String
>
attributes
,
List
<
XStreamDOM
>
children
)
{
this
.
tagName
=
tagName
;
this
.
attributes
=
toAttributeList
(
attributes
);
this
.
value
=
null
;
this
.
children
=
children
;
}
private
XStreamDOM
(
String
tagName
,
String
[]
attributes
,
List
<
XStreamDOM
>
children
,
String
value
)
{
this
.
tagName
=
tagName
;
this
.
attributes
=
attributes
;
this
.
children
=
children
;
this
.
value
=
value
;
}
private
String
[]
toAttributeList
(
Map
<
String
,
String
>
attributes
)
{
String
[]
r
=
new
String
[
attributes
.
size
()*
2
];
int
i
=
0
;
for
(
Entry
<
String
,
String
>
e
:
attributes
.
entrySet
())
{
r
[
i
++]
=
e
.
getKey
();
r
[
i
++]
=
e
.
getValue
();
}
return
r
;
}
public
String
getTagName
()
{
return
tagName
;
}
/**
* Unmarshals this DOM into an object via the given XStream.
*/
public
<
T
>
T
unmarshal
(
XStream
xs
)
{
return
(
T
)
xs
.
unmarshal
(
newReader
());
}
public
<
T
>
T
unmarshal
(
XStream
xs
,
T
root
)
{
return
(
T
)
xs
.
unmarshal
(
newReader
(),
root
);
}
public
String
getAttribute
(
String
name
)
{
for
(
int
i
=
0
;
i
<
attributes
.
length
;
i
+=
2
)
if
(
attributes
[
i
].
equals
(
name
))
return
attributes
[
i
+
1
];
return
null
;
}
public
int
getAttributeCount
()
{
return
attributes
.
length
/
2
;
}
private
String
getAttributeName
(
int
index
)
{
return
attributes
[
index
*
2
];
}
public
String
getAttribute
(
int
index
)
{
return
attributes
[
index
*
2
+
1
];
}
public
Iterator
<
String
>
getAttributeNames
()
{
return
new
AbstractList
<
String
>()
{
public
String
get
(
int
index
)
{
return
getAttributeName
(
index
);
}
public
int
size
()
{
return
getAttributeCount
();
}
}.
iterator
();
}
public
String
getValue
()
{
return
value
;
}
public
List
<
XStreamDOM
>
getChildren
()
{
return
children
;
}
/**
* Returns a new {@link HierarchicalStreamReader} that reads a sub-tree rooted at this node.
*/
public
HierarchicalStreamReader
newReader
()
{
return
new
ReaderImpl
(
this
);
}
/**
* Returns a new {@link HierarchicalStreamWriter} for marshalling objects into {@link XStreamDOM}.
* After the writer receives the calls, call {@Link WriterImpl#getOutput()} to obtain the populated tree.
*/
public
static
WriterImpl
newWriter
()
{
return
new
WriterImpl
();
}
/**
* Marshals the given object with the given XStream into {@link XStreamDOM} and return it.
*/
public
static
XStreamDOM
from
(
XStream
xs
,
Object
obj
)
{
WriterImpl
w
=
newWriter
();
xs
.
marshal
(
obj
,
w
);
return
w
.
getOutput
();
}
private
static
class
ReaderImpl
extends
AbstractXmlReader
implements
DocumentReader
{
private
static
class
Pointer
{
final
XStreamDOM
node
;
int
pos
;
private
Pointer
(
XStreamDOM
node
)
{
this
.
node
=
node
;
}
public
String
peekNextChild
()
{
if
(
hasMoreChildren
())
return
node
.
children
.
get
(
pos
).
tagName
;
return
null
;
}
public
boolean
hasMoreChildren
()
{
return
node
.
children
!=
null
&&
pos
<
node
.
children
.
size
();
}
public
String
xpath
()
{
XStreamDOM
child
=
node
.
children
.
get
(
pos
-
1
);
int
count
=
0
;
for
(
int
i
=
0
;
i
<
pos
-
1
;
i
++)
if
(
node
.
children
.
get
(
i
).
tagName
.
equals
(
child
.
tagName
))
count
++;
boolean
more
=
false
;
for
(
int
i
=
pos
;
!
more
&&
i
<
node
.
children
.
size
();
i
++)
if
(
node
.
children
.
get
(
i
).
tagName
.
equals
(
child
.
tagName
))
more
=
true
;
if
(
count
==
0
&&
!
more
)
return
child
.
tagName
;
// sole child
return
child
.
tagName
+
'['
+
count
+
']'
;
}
}
private
final
Stack
<
Pointer
>
pointers
=
new
Stack
<
Pointer
>();
public
ReaderImpl
(
XStreamDOM
current
)
{
super
(
new
XmlFriendlyReplacer
());
pointers
.
push
(
new
Pointer
(
current
));
}
private
Pointer
current
()
{
return
pointers
.
peek
();
}
public
Object
getCurrent
()
{
return
current
().
node
;
}
public
boolean
hasMoreChildren
()
{
return
current
().
hasMoreChildren
();
}
public
HierarchicalStreamReader
underlyingReader
()
{
return
this
;
}
public
void
moveDown
()
{
Pointer
p
=
current
();
pointers
.
push
(
new
Pointer
(
p
.
node
.
children
.
get
(
p
.
pos
++)));
}
public
void
moveUp
()
{
pointers
.
pop
();
}
public
Iterator
getAttributeNames
()
{
return
current
().
node
.
getAttributeNames
();
}
public
void
appendErrors
(
ErrorWriter
errorWriter
)
{
StringBuilder
buf
=
new
StringBuilder
();
Pointer
parent
=
null
;
for
(
Pointer
cur
:
pointers
)
{
if
(
parent
!=
null
)
{
buf
.
append
(
'/'
).
append
(
parent
.
xpath
());
}
else
{
buf
.
append
(
cur
.
node
.
tagName
);
}
parent
=
cur
;
}
errorWriter
.
add
(
"xpath"
,
buf
.
toString
());
}
public
void
close
()
{
}
public
String
peekNextChild
()
{
return
current
().
peekNextChild
();
}
public
String
getNodeName
()
{
return
current
().
node
.
tagName
;
}
public
String
getValue
()
{
return
Util
.
fixNull
(
current
().
node
.
value
);
}
public
String
getAttribute
(
String
name
)
{
return
current
().
node
.
getAttribute
(
name
);
}
public
String
getAttribute
(
int
index
)
{
return
current
().
node
.
getAttribute
(
index
);
}
public
int
getAttributeCount
()
{
return
current
().
node
.
getAttributeCount
();
}
public
String
getAttributeName
(
int
index
)
{
return
current
().
node
.
getAttributeName
(
index
);
}
}
public
static
class
WriterImpl
extends
AbstractXmlWriter
{
private
static
class
Pending
{
final
String
tagName
;
List
<
XStreamDOM
>
children
;
List
<
String
>
attributes
=
new
ArrayList
<
String
>();
String
value
;
private
Pending
(
String
tagName
)
{
this
.
tagName
=
tagName
;
}
void
addChild
(
XStreamDOM
dom
)
{
if
(
children
==
null
)
children
=
new
ArrayList
<
XStreamDOM
>();
children
.
add
(
dom
);
}
XStreamDOM
toDOM
()
{
return
new
XStreamDOM
(
tagName
,
attributes
.
toArray
(
new
String
[
attributes
.
size
()]),
children
,
value
);
}
}
private
final
Stack
<
Pending
>
pendings
=
new
Stack
<
Pending
>();
public
WriterImpl
()
{
pendings
.
push
(
new
Pending
(
null
));
// to get the final result
}
public
void
startNode
(
String
name
)
{
pendings
.
push
(
new
Pending
(
escapeXmlName
(
name
)));
}
public
void
endNode
()
{
XStreamDOM
dom
=
pendings
.
pop
().
toDOM
();
pendings
.
peek
().
addChild
(
dom
);
}
public
void
addAttribute
(
String
name
,
String
value
)
{
List
<
String
>
atts
=
pendings
.
peek
().
attributes
;
atts
.
add
(
escapeXmlName
(
name
));
atts
.
add
(
value
);
}
public
void
setValue
(
String
text
)
{
pendings
.
peek
().
value
=
text
;
}
public
void
flush
()
{
}
public
void
close
()
{
}
public
HierarchicalStreamWriter
underlyingWriter
()
{
return
this
;
}
public
XStreamDOM
getOutput
()
{
if
(
pendings
.
size
()!=
1
)
throw
new
IllegalStateException
();
return
pendings
.
peek
().
children
.
get
(
0
);
}
}
public
static
class
ConverterImpl
implements
Converter
{
public
boolean
canConvert
(
Class
type
)
{
return
type
==
XStreamDOM
.
class
;
}
public
void
marshal
(
Object
source
,
HierarchicalStreamWriter
w
,
MarshallingContext
context
)
{
XStreamDOM
dom
=
(
XStreamDOM
)
source
;
w
.
startNode
(
dom
.
tagName
);
for
(
int
i
=
0
;
i
<
dom
.
attributes
.
length
;
i
+=
2
)
w
.
addAttribute
(
dom
.
attributes
[
i
],
dom
.
attributes
[
i
+
1
]);
if
(
dom
.
value
!=
null
)
w
.
setValue
(
dom
.
value
);
else
{
for
(
XStreamDOM
c
:
dom
.
children
)
{
marshal
(
c
,
w
,
context
);
}
}
w
.
endNode
();
}
public
XStreamDOM
unmarshal
(
HierarchicalStreamReader
r
,
UnmarshallingContext
context
)
{
r
.
moveDown
();
String
name
=
r
.
getNodeName
();
int
c
=
r
.
getAttributeCount
();
String
[]
attributes
=
new
String
[
c
*
2
];
for
(
int
i
=
0
;
i
<
c
;
i
++)
{
attributes
[
i
*
2
]
=
r
.
getAttributeName
(
i
);
attributes
[
i
*
2
+
1
]
=
r
.
getAttribute
(
i
);
}
List
<
XStreamDOM
>
children
=
null
;
String
value
=
null
;
if
(
r
.
hasMoreChildren
())
{
children
=
new
ArrayList
<
XStreamDOM
>();
while
(
r
.
hasMoreChildren
())
{
children
.
add
(
unmarshal
(
r
,
context
));
}
}
else
{
value
=
r
.
getValue
();
}
r
.
moveUp
();
return
new
XStreamDOM
(
name
,
attributes
,
children
,
value
);
}
}
}
core/src/test/java/jenkins/util/xstream/XStreamDOMTest.java
0 → 100644
浏览文件 @
f527a54a
/*
* The MIT License
*
* Copyright (c) 2012, 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
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package
jenkins.util.xstream
;
import
hudson.util.XStream2
;
import
junit.framework.TestCase
;
import
org.apache.commons.io.IOUtils
;
import
java.io.IOException
;
import
java.util.Collections
;
/**
* @author Kohsuke Kawaguchi
*/
public
class
XStreamDOMTest
extends
TestCase
{
private
XStream2
xs
;
public
static
class
Foo
{
XStreamDOM
bar
;
XStreamDOM
zot
;
}
@Override
protected
void
setUp
()
throws
Exception
{
super
.
setUp
();
xs
=
new
XStream2
();
xs
.
alias
(
"foo"
,
Foo
.
class
);
}
public
void
testMarshal
()
throws
IOException
{
Foo
foo
=
createSomeFoo
();
String
xml
=
xs
.
toXML
(
foo
);
System
.
out
.
println
(
xml
);
assertEquals
(
IOUtils
.
toString
(
getClass
().
getResourceAsStream
(
"XStreamDOMTest.data1.xml"
)).
trim
(),
xml
.
trim
());
}
private
Foo
createSomeFoo
()
{
Foo
foo
=
new
Foo
();
foo
.
bar
=
new
XStreamDOM
(
"test1"
,
Collections
.
singletonMap
(
"key"
,
"value"
),
"text!"
);
foo
.
zot
=
new
XStreamDOM
(
"test2"
,
Collections
.
singletonMap
(
"key"
,
"value"
),
Collections
.
singletonList
(
foo
.
bar
));
return
foo
;
}
public
void
testUnmarshal
()
throws
Exception
{
Foo
foo
=
(
Foo
)
xs
.
fromXML
(
getClass
().
getResourceAsStream
(
"XStreamDOMTest.data1.xml"
));
assertEquals
(
"test1"
,
foo
.
bar
.
getTagName
());
assertEquals
(
"value"
,
foo
.
bar
.
getAttribute
(
"key"
));
assertEquals
(
"text!"
,
foo
.
bar
.
getValue
());
}
public
void
testWriteToDOM
()
throws
Exception
{
// roundtrip via DOM
XStreamDOM
dom
=
XStreamDOM
.
from
(
xs
,
createSomeFoo
());
Foo
foo
=
dom
.
unmarshal
(
xs
);
String
xml
=
xs
.
toXML
(
foo
);
System
.
out
.
println
(
xml
);
assertEquals
(
IOUtils
.
toString
(
getClass
().
getResourceAsStream
(
"XStreamDOMTest.data1.xml"
)).
trim
(),
xml
.
trim
());
}
}
core/src/test/resources/jenkins/util/xstream/XStreamDOMTest.data1.xml
0 → 100644
浏览文件 @
f527a54a
<foo>
<bar>
<test1
key=
"value"
>
text!
</test1>
</bar>
<zot>
<test2
key=
"value"
>
<test1
key=
"value"
>
text!
</test1>
</test2>
</zot>
</foo>
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录