Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
爱吃血肠
spring-framework
提交
b1e2a2ec
S
spring-framework
项目概览
爱吃血肠
/
spring-framework
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
S
spring-framework
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
b1e2a2ec
编写于
1月 27, 2010
作者:
A
Arjen Poutsma
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
SPR-6577 - MarshallingView auto detect model with Jaxb2Marshaller chooses the wrong object
上级
71d7b22d
变更
5
显示空白变更内容
内联
并排
Showing
5 changed file
with
183 addition
and
42 deletion
+183
-42
org.springframework.oxm/src/main/java/org/springframework/oxm/GenericMarshaller.java
.../main/java/org/springframework/oxm/GenericMarshaller.java
+37
-0
org.springframework.oxm/src/main/java/org/springframework/oxm/GenericUnmarshaller.java
...ain/java/org/springframework/oxm/GenericUnmarshaller.java
+37
-0
org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
...in/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
+61
-21
org.springframework.oxm/src/main/java/org/springframework/oxm/mime/MimeUnmarshaller.java
...n/java/org/springframework/oxm/mime/MimeUnmarshaller.java
+1
-1
org.springframework.oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java
...va/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java
+47
-20
未找到文件。
org.springframework.oxm/src/main/java/org/springframework/oxm/GenericMarshaller.java
0 → 100644
浏览文件 @
b1e2a2ec
/*
* Copyright 2002-2010 the original author or authors.
*
* 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
org.springframework.oxm
;
import
java.lang.reflect.Type
;
/**
* Subinterface of {@link Marshaller} that has support for Java 5 generics.
*
* @author Arjen Poutsma
* @sicne 3.0.1
*/
public
interface
GenericMarshaller
extends
Marshaller
{
/**
* Indicates whether this marshaller can marshal instances of the supplied generic type.
* @param genericType the type that this marshaller is being asked if it can marshal
* @return <code>true</code> if this marshaller can indeed marshal instances of the supplied type;
* <code>false</code> otherwise
*/
boolean
supports
(
Type
genericType
);
}
org.springframework.oxm/src/main/java/org/springframework/oxm/GenericUnmarshaller.java
0 → 100644
浏览文件 @
b1e2a2ec
/*
* Copyright 2002-2010 the original author or authors.
*
* 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
org.springframework.oxm
;
import
java.lang.reflect.Type
;
/**
* Subinterface of {@link Unmarshaller} that has support for Java 5 generics.
*
* @author Arjen Poutsma
* @sicne 3.0.1
*/
public
interface
GenericUnmarshaller
extends
Unmarshaller
{
/**
* Indicates whether this marshaller can marshal instances of the supplied generic type.
* @param genericType the type that this marshaller is being asked if it can marshal
* @return <code>true</code> if this marshaller can indeed marshal instances of the supplied type;
* <code>false</code> otherwise
*/
boolean
supports
(
Type
genericType
);
}
\ No newline at end of file
org.springframework.oxm/src/main/java/org/springframework/oxm/jaxb/Jaxb2Marshaller.java
浏览文件 @
b1e2a2ec
...
...
@@ -28,6 +28,8 @@ import java.net.URLEncoder;
import
java.util.Arrays
;
import
java.util.Map
;
import
java.util.UUID
;
import
java.lang.reflect.Type
;
import
java.lang.reflect.ParameterizedType
;
import
javax.activation.DataHandler
;
import
javax.activation.DataSource
;
import
javax.xml.XMLConstants
;
...
...
@@ -41,6 +43,7 @@ import javax.xml.bind.Unmarshaller;
import
javax.xml.bind.ValidationEventHandler
;
import
javax.xml.bind.ValidationException
;
import
javax.xml.bind.annotation.XmlRootElement
;
import
javax.xml.bind.annotation.XmlType
;
import
javax.xml.bind.annotation.adapters.XmlAdapter
;
import
javax.xml.bind.attachment.AttachmentMarshaller
;
import
javax.xml.bind.attachment.AttachmentUnmarshaller
;
...
...
@@ -70,6 +73,8 @@ import org.springframework.oxm.UncategorizedMappingException;
import
org.springframework.oxm.UnmarshallingFailureException
;
import
org.springframework.oxm.ValidationFailureException
;
import
org.springframework.oxm.XmlMappingException
;
import
org.springframework.oxm.GenericMarshaller
;
import
org.springframework.oxm.GenericUnmarshaller
;
import
org.springframework.oxm.mime.MimeContainer
;
import
org.springframework.oxm.mime.MimeMarshaller
;
import
org.springframework.oxm.mime.MimeUnmarshaller
;
...
...
@@ -101,7 +106,9 @@ import org.springframework.util.xml.StaxUtils;
* @see #setAdapters(XmlAdapter[])
* @since 3.0
*/
public
class
Jaxb2Marshaller
implements
MimeMarshaller
,
MimeUnmarshaller
,
BeanClassLoaderAware
,
InitializingBean
{
public
class
Jaxb2Marshaller
implements
MimeMarshaller
,
MimeUnmarshaller
,
GenericMarshaller
,
GenericUnmarshaller
,
BeanClassLoaderAware
,
InitializingBean
{
private
static
final
String
CID
=
"cid:"
;
...
...
@@ -143,6 +150,12 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
private
boolean
lazyInit
=
false
;
/**
* Returns the JAXB context path.
*/
public
String
getContextPath
()
{
return
contextPath
;
}
/**
* Set a JAXB context path.
...
...
@@ -161,6 +174,13 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
this
.
contextPath
=
StringUtils
.
arrayToDelimitedString
(
contextPaths
,
":"
);
}
/**
* Returns the list of Java classes to be recognized by a newly created JAXBContext.
*/
public
Class
[]
getClassesToBeBound
()
{
return
classesToBeBound
;
}
/**
* Set the list of Java classes to be recognized by a newly created JAXBContext.
* Setting this property or {@link #setContextPath "contextPath"} is required.
...
...
@@ -280,10 +300,10 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
public
final
void
afterPropertiesSet
()
throws
Exception
{
if
(
StringUtils
.
hasLength
(
this
.
contextPath
)
&&
!
ObjectUtils
.
isEmpty
(
this
.
classesToBeBound
))
{
if
(
StringUtils
.
hasLength
(
getContextPath
())
&&
!
ObjectUtils
.
isEmpty
(
getClassesToBeBound
()
))
{
throw
new
IllegalArgumentException
(
"Specify either 'contextPath' or 'classesToBeBound property'; not both"
);
}
else
if
(!
StringUtils
.
hasLength
(
this
.
contextPath
)
&&
ObjectUtils
.
isEmpty
(
this
.
classesToBeBound
))
{
else
if
(!
StringUtils
.
hasLength
(
getContextPath
())
&&
ObjectUtils
.
isEmpty
(
getClassesToBeBound
()
))
{
throw
new
IllegalArgumentException
(
"Setting either 'contextPath' or 'classesToBeBound' is required"
);
}
if
(!
lazyInit
)
{
...
...
@@ -297,10 +317,10 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
protected
synchronized
JAXBContext
getJaxbContext
()
{
if
(
this
.
jaxbContext
==
null
)
{
try
{
if
(
StringUtils
.
hasLength
(
this
.
contextPath
))
{
if
(
StringUtils
.
hasLength
(
getContextPath
()
))
{
this
.
jaxbContext
=
createJaxbContextFromContextPath
();
}
else
if
(!
ObjectUtils
.
isEmpty
(
this
.
classesToBeBound
))
{
else
if
(!
ObjectUtils
.
isEmpty
(
getClassesToBeBound
()
))
{
this
.
jaxbContext
=
createJaxbContextFromClasses
();
}
}
...
...
@@ -313,22 +333,22 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
private
JAXBContext
createJaxbContextFromContextPath
()
throws
JAXBException
{
if
(
logger
.
isInfoEnabled
())
{
logger
.
info
(
"Creating JAXBContext with context path ["
+
this
.
contextPath
+
"]"
);
logger
.
info
(
"Creating JAXBContext with context path ["
+
getContextPath
()
+
"]"
);
}
if
(
this
.
jaxbContextProperties
!=
null
)
{
if
(
this
.
beanClassLoader
!=
null
)
{
return
JAXBContext
.
newInstance
(
this
.
contextPath
,
this
.
beanClassLoader
,
this
.
jaxbContextProperties
);
return
JAXBContext
.
newInstance
(
getContextPath
()
,
this
.
beanClassLoader
,
this
.
jaxbContextProperties
);
}
else
{
return
JAXBContext
.
newInstance
(
this
.
contextPath
,
ClassUtils
.
getDefaultClassLoader
(),
this
.
jaxbContextProperties
);
return
JAXBContext
.
newInstance
(
getContextPath
()
,
ClassUtils
.
getDefaultClassLoader
(),
this
.
jaxbContextProperties
);
}
}
else
{
if
(
this
.
beanClassLoader
!=
null
)
{
return
JAXBContext
.
newInstance
(
this
.
contextPath
,
this
.
beanClassLoader
);
return
JAXBContext
.
newInstance
(
getContextPath
()
,
this
.
beanClassLoader
);
}
else
{
return
JAXBContext
.
newInstance
(
this
.
contextPath
);
return
JAXBContext
.
newInstance
(
getContextPath
()
);
}
}
}
...
...
@@ -336,13 +356,13 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
private
JAXBContext
createJaxbContextFromClasses
()
throws
JAXBException
{
if
(
logger
.
isInfoEnabled
())
{
logger
.
info
(
"Creating JAXBContext with classes to be bound ["
+
StringUtils
.
arrayToCommaDelimitedString
(
this
.
classesToBeBound
)
+
"]"
);
StringUtils
.
arrayToCommaDelimitedString
(
getClassesToBeBound
()
)
+
"]"
);
}
if
(
this
.
jaxbContextProperties
!=
null
)
{
return
JAXBContext
.
newInstance
(
this
.
classesToBeBound
,
this
.
jaxbContextProperties
);
return
JAXBContext
.
newInstance
(
getClassesToBeBound
()
,
this
.
jaxbContextProperties
);
}
else
{
return
JAXBContext
.
newInstance
(
this
.
classesToBeBound
);
return
JAXBContext
.
newInstance
(
getClassesToBeBound
()
);
}
}
...
...
@@ -367,15 +387,35 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
public
boolean
supports
(
Class
<?>
clazz
)
{
if
(
JAXBElement
.
class
.
isAssignableFrom
(
clazz
))
{
return
true
;
return
supportsInternal
(
clazz
,
true
);
}
else
if
(
AnnotationUtils
.
findAnnotation
(
clazz
,
XmlRootElement
.
class
)
!=
null
)
{
return
true
;
public
boolean
supports
(
Type
genericType
)
{
if
(
genericType
instanceof
ParameterizedType
)
{
ParameterizedType
parameterizedType
=
(
ParameterizedType
)
genericType
;
if
(
JAXBElement
.
class
.
equals
(
parameterizedType
.
getRawType
())
&&
parameterizedType
.
getActualTypeArguments
().
length
==
1
&&
parameterizedType
.
getActualTypeArguments
()[
0
]
instanceof
Class
)
{
Class
typeArgument
=
(
Class
)
parameterizedType
.
getActualTypeArguments
()[
0
];
return
supportsInternal
(
typeArgument
,
false
);
}
}
else
if
(
genericType
instanceof
Class
)
{
Class
clazz
=
(
Class
)
genericType
;
return
supportsInternal
(
clazz
,
true
);
}
return
false
;
}
private
boolean
supportsInternal
(
Class
<?>
clazz
,
boolean
checkForXmlRootElement
)
{
if
(
checkForXmlRootElement
&&
AnnotationUtils
.
findAnnotation
(
clazz
,
XmlRootElement
.
class
)
==
null
)
{
return
false
;
}
if
(
AnnotationUtils
.
findAnnotation
(
clazz
,
XmlType
.
class
)
==
null
)
{
return
false
;
}
if
(
StringUtils
.
hasLength
(
this
.
contextPath
))
{
if
(
StringUtils
.
hasLength
(
getContextPath
()
))
{
String
packageName
=
ClassUtils
.
getPackageName
(
clazz
);
String
[]
contextPaths
=
StringUtils
.
tokenizeToStringArray
(
this
.
contextPath
,
":"
);
String
[]
contextPaths
=
StringUtils
.
tokenizeToStringArray
(
getContextPath
()
,
":"
);
for
(
String
contextPath
:
contextPaths
)
{
if
(
contextPath
.
equals
(
packageName
))
{
return
true
;
...
...
@@ -383,8 +423,8 @@ public class Jaxb2Marshaller implements MimeMarshaller, MimeUnmarshaller, BeanCl
}
return
false
;
}
else
if
(!
ObjectUtils
.
isEmpty
(
this
.
classesToBeBound
))
{
return
Arrays
.
asList
(
this
.
classesToBeBound
).
contains
(
clazz
);
else
if
(!
ObjectUtils
.
isEmpty
(
getClassesToBeBound
()
))
{
return
Arrays
.
asList
(
getClassesToBeBound
()
).
contains
(
clazz
);
}
return
false
;
}
...
...
org.springframework.oxm/src/main/java/org/springframework/oxm/mime/MimeUnmarshaller.java
浏览文件 @
b1e2a2ec
...
...
@@ -23,7 +23,7 @@ import org.springframework.oxm.Unmarshaller;
import
org.springframework.oxm.XmlMappingException
;
/**
* Subinterface of {@link org.springframework.oxm.
M
arshaller} that can use MIME attachments
* Subinterface of {@link org.springframework.oxm.
Unm
arshaller} that can use MIME attachments
* to optimize storage of binary data. Attachments can be added as MTOM, XOP, or SwA.
*
* @author Arjen Poutsma
...
...
org.springframework.oxm/src/test/java/org/springframework/oxm/jaxb/Jaxb2MarshallerTests.java
浏览文件 @
b1e2a2ec
...
...
@@ -18,12 +18,16 @@ package org.springframework.oxm.jaxb;
import
java.io.StringWriter
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Type
;
import
java.util.Collections
;
import
javax.activation.DataHandler
;
import
javax.activation.FileDataSource
;
import
javax.xml.transform.Result
;
import
javax.xml.transform.sax.SAXResult
;
import
javax.xml.transform.stream.StreamResult
;
import
javax.xml.bind.annotation.XmlRootElement
;
import
javax.xml.bind.annotation.XmlType
;
import
javax.xml.bind.JAXBElement
;
import
static
org
.
custommonkey
.
xmlunit
.
XMLAssert
.*;
import
static
org
.
easymock
.
EasyMock
.*;
...
...
@@ -35,10 +39,12 @@ import org.xml.sax.Locator;
import
org.springframework.core.io.ClassPathResource
;
import
org.springframework.core.io.Resource
;
import
org.springframework.core.GenericTypeResolver
;
import
org.springframework.oxm.AbstractMarshallerTests
;
import
org.springframework.oxm.Marshaller
;
import
org.springframework.oxm.UncategorizedMappingException
;
import
org.springframework.oxm.XmlMappingException
;
import
org.springframework.oxm.GenericMarshaller
;
import
org.springframework.oxm.jaxb.test.FlightType
;
import
org.springframework.oxm.jaxb.test.Flights
;
import
org.springframework.oxm.jaxb.test.ObjectFactory
;
...
...
@@ -142,11 +148,8 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
@Test
public
void
supportsContextPath
()
throws
Exception
{
Method
createFlights
=
ObjectFactory
.
class
.
getDeclaredMethod
(
"createFlights"
);
assertTrue
(
"Jaxb2Marshaller does not support Flights"
,
marshaller
.
supports
(
createFlights
.
getReturnType
()));
Method
createFlight
=
ObjectFactory
.
class
.
getDeclaredMethod
(
"createFlight"
,
FlightType
.
class
);
assertTrue
(
"Jaxb2Marshaller does not support JAXBElement<FlightsType>"
,
marshaller
.
supports
(
createFlight
.
getReturnType
()));
testSupports
(
marshaller
);
}
@Test
...
...
@@ -154,11 +157,30 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
marshaller
=
new
Jaxb2Marshaller
();
marshaller
.
setClassesToBeBound
(
new
Class
[]{
Flights
.
class
,
FlightType
.
class
});
marshaller
.
afterPropertiesSet
();
Method
createFlights
=
ObjectFactory
.
class
.
getDeclaredMethod
(
"createFlights"
);
assertTrue
(
"Jaxb2Marshaller does not support Flights"
,
marshaller
.
supports
(
createFlights
.
getReturnType
()));
Method
createFlight
=
ObjectFactory
.
class
.
getDeclaredMethod
(
"createFlight"
,
FlightType
.
class
);
testSupports
(
marshaller
);
}
private
void
testSupports
(
Jaxb2Marshaller
marshaller
)
throws
Exception
{
assertTrue
(
"Jaxb2Marshaller does not support Flights class"
,
marshaller
.
supports
(
Flights
.
class
));
assertTrue
(
"Jaxb2Marshaller does not support Flights generic type"
,
marshaller
.
supports
((
Type
)
Flights
.
class
));
assertFalse
(
"Jaxb2Marshaller supports FlightType class"
,
marshaller
.
supports
(
FlightType
.
class
));
Method
method
=
ObjectFactory
.
class
.
getDeclaredMethod
(
"createFlight"
,
FlightType
.
class
);
assertTrue
(
"Jaxb2Marshaller does not support JAXBElement<FlightsType>"
,
marshaller
.
supports
(
createFlight
.
getReturnType
()));
marshaller
.
supports
(
method
.
getGenericReturnType
()));
assertFalse
(
"Jaxb2Marshaller supports class not in context path"
,
marshaller
.
supports
(
DummyRootElement
.
class
));
assertFalse
(
"Jaxb2Marshaller supports type not in context path"
,
marshaller
.
supports
((
Type
)
DummyRootElement
.
class
));
method
=
getClass
().
getDeclaredMethod
(
"createDummyRootElement"
);
assertFalse
(
"Jaxb2Marshaller supports JAXBElement not in context path"
,
marshaller
.
supports
(
method
.
getGenericReturnType
()));
assertFalse
(
"Jaxb2Marshaller supports class not in context path"
,
marshaller
.
supports
(
DummyType
.
class
));
assertFalse
(
"Jaxb2Marshaller supports type not in context path"
,
marshaller
.
supports
((
Type
)
DummyType
.
class
));
method
=
getClass
().
getDeclaredMethod
(
"createDummyType"
);
assertFalse
(
"Jaxb2Marshaller supports JAXBElement not in context path"
,
marshaller
.
supports
(
method
.
getGenericReturnType
()));
}
@Test
...
...
@@ -185,19 +207,24 @@ public class Jaxb2MarshallerTests extends AbstractMarshallerTests {
assertTrue
(
"No XML written"
,
writer
.
toString
().
length
()
>
0
);
}
@Test
public
void
subclass
()
throws
Exception
{
assertTrue
(
"Flights subclass is not supported"
,
marshaller
.
supports
(
FlightsSubclass
.
class
));
FlightType
flight
=
new
FlightType
();
flight
.
setNumber
(
42L
);
FlightsSubclass
flights
=
new
FlightsSubclass
();
flights
.
getFlight
().
add
(
flight
);
StringWriter
writer
=
new
StringWriter
();
marshaller
.
marshal
(
flights
,
new
StreamResult
(
writer
));
assertXMLEqual
(
"Marshaller writes invalid StreamResult"
,
EXPECTED_STRING
,
writer
.
toString
());
@XmlRootElement
public
static
class
DummyRootElement
{
private
DummyType
t
=
new
DummyType
();
}
private
static
class
FlightsSubclass
extends
Flights
{
@XmlType
public
static
class
DummyType
{
private
String
s
=
"Hello"
;
}
public
JAXBElement
<
DummyRootElement
>
createDummyRootElement
()
{
return
null
;
}
public
JAXBElement
<
DummyType
>
createDummyType
()
{
return
null
;
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录