Skip to content

Commit b920678

Browse files
committed
2 parents ffd060b + 0aecba7 commit b920678

File tree

9 files changed

+383
-236
lines changed

9 files changed

+383
-236
lines changed

basic/src/main/java/org/jvnet/jaxb2_commons/plugin/Customizations.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ public class Customizations {
1111

1212
public static QName IGNORED_ELEMENT_NAME = new QName(NAMESPACE_URI,
1313
"ignored");
14+
15+
public static QName PROPERTY_ELEMENT_NAME = new QName(NAMESPACE_URI,
16+
"property");
1417

1518
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.jvnet.jaxb2_commons.plugin.customizations;
2+
3+
import javax.xml.namespace.QName;
4+
5+
public class Customizations {
6+
7+
public static String NAMESPACE_URI = "http://jaxb2-commons.dev.java.net/basic/customizations";
8+
9+
public static String CUSTOMIZATIONS_LOCAL_PART = "customizations";
10+
11+
public static QName CUSTOMIZATIONS_ELEMENT_NAME = new QName(NAMESPACE_URI, CUSTOMIZATIONS_LOCAL_PART);
12+
13+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
package org.jvnet.jaxb2_commons.plugin.customizations;
2+
3+
import java.io.File;
4+
import java.io.FileInputStream;
5+
import java.io.IOException;
6+
import java.io.InputStream;
7+
import java.text.MessageFormat;
8+
import java.util.LinkedList;
9+
import java.util.List;
10+
11+
import javax.xml.namespace.QName;
12+
import javax.xml.parsers.DocumentBuilder;
13+
import javax.xml.parsers.DocumentBuilderFactory;
14+
import javax.xml.parsers.ParserConfigurationException;
15+
16+
import org.jvnet.jaxb2_commons.plugin.AbstractParameterizablePlugin;
17+
import org.jvnet.jaxb2_commons.util.ClassUtils;
18+
import org.w3c.dom.Document;
19+
import org.w3c.dom.Element;
20+
import org.w3c.dom.Node;
21+
import org.w3c.dom.NodeList;
22+
import org.xml.sax.ErrorHandler;
23+
import org.xml.sax.SAXException;
24+
25+
import com.sun.tools.xjc.model.CClassInfo;
26+
import com.sun.tools.xjc.model.CEnumConstant;
27+
import com.sun.tools.xjc.model.CEnumLeafInfo;
28+
import com.sun.tools.xjc.model.CPluginCustomization;
29+
import com.sun.tools.xjc.model.CPropertyInfo;
30+
import com.sun.tools.xjc.model.Model;
31+
32+
public class CustomizationsPlugin extends AbstractParameterizablePlugin {
33+
34+
private final DocumentBuilderFactory documentBuilderFactory;
35+
{
36+
documentBuilderFactory = DocumentBuilderFactory.newInstance();
37+
documentBuilderFactory.setNamespaceAware(true);
38+
}
39+
40+
private File directory;
41+
42+
public File getDirectory() {
43+
return directory;
44+
}
45+
46+
public void setDirectory(File customizationsDirectory) {
47+
this.directory = customizationsDirectory;
48+
}
49+
50+
private boolean verbose;
51+
52+
public boolean isVerbose() {
53+
return verbose;
54+
}
55+
56+
public void setVerbose(boolean verbose) {
57+
this.verbose = verbose;
58+
}
59+
60+
@Override
61+
public String getOptionName() {
62+
return "Xcustomizations";
63+
}
64+
65+
@Override
66+
public String getUsage() {
67+
return " -Xcustomizations : reads and adds customizations from files";
68+
}
69+
70+
@Override
71+
public void postProcessModel(Model model, ErrorHandler errorHandler) {
72+
if (getDirectory() == null) {
73+
logger.warn(
74+
"Customizations directory is not provided, please use the -Xcustomizations-directory=<directory> command line argument to provide it.");
75+
} else if (!getDirectory().exists()) {
76+
logger.warn(MessageFormat.format("Customizations directory [{0}] does not exist.",
77+
getDirectory().getAbsolutePath()));
78+
} else if (!getDirectory().isDirectory()) {
79+
logger.warn(MessageFormat.format("Customizations directory [{0}] is not a directory.",
80+
getDirectory().getAbsolutePath()));
81+
} else {
82+
postProcessModel(model);
83+
}
84+
}
85+
86+
private void postProcessModel(Model model) {
87+
for (final CClassInfo classInfo : model.beans().values()) {
88+
postProcessClassInfo(model, classInfo);
89+
}
90+
for (final CEnumLeafInfo enumLeafInfo : model.enums().values()) {
91+
postProcessEnumLeafInfo(model, enumLeafInfo);
92+
}
93+
}
94+
95+
private void postProcessClassInfo(Model model, CClassInfo classInfo) {
96+
final String packagedClassName = ClassUtils.getPackagedClassName(classInfo);
97+
final String customizationsFileName = packagedClassName.replace(".", "/") + ".xml";
98+
99+
final List<CPluginCustomization> customizations = readCustomizations(customizationsFileName);
100+
101+
classInfo.getCustomizations().addAll(customizations);
102+
103+
for (CPropertyInfo propertyInfo: classInfo.getProperties())
104+
{
105+
postProcessPropertyInfo(model, classInfo, propertyInfo);
106+
}
107+
}
108+
109+
private void postProcessPropertyInfo(Model model, CClassInfo classInfo, CPropertyInfo propertyInfo) {
110+
final String packagedClassName = ClassUtils.getPackagedClassName(classInfo);
111+
final String customizationsFileName = packagedClassName.replace(".", "/") + "." +propertyInfo.getName(false) + ".xml";
112+
final List<CPluginCustomization> customizations = readCustomizations(customizationsFileName);
113+
propertyInfo.getCustomizations().addAll(customizations);
114+
}
115+
116+
private void postProcessEnumLeafInfo(Model model, CEnumLeafInfo enumLeafInfo) {
117+
final String packagedClassName = ClassUtils.getPackagedClassName(enumLeafInfo);
118+
final String customizationsFileName = packagedClassName.replace(".", "/") + ".xml";
119+
120+
final List<CPluginCustomization> customizations = readCustomizations(customizationsFileName);
121+
122+
enumLeafInfo.getCustomizations().addAll(customizations);
123+
for (CEnumConstant enumConstant : enumLeafInfo.getConstants()) {
124+
postProcessEnumConstant(model, enumLeafInfo, enumConstant);
125+
}
126+
}
127+
128+
private void postProcessEnumConstant(Model model, CEnumLeafInfo enumLeafInfo, CEnumConstant enumConstant) {
129+
final String packagedClassName = ClassUtils.getPackagedClassName(enumLeafInfo);
130+
final String customizationsFileName = packagedClassName.replace(".", "/") + "." +enumConstant.getName() + ".xml";
131+
final List<CPluginCustomization> customizations = readCustomizations(customizationsFileName);
132+
enumConstant.getCustomizations().addAll(customizations);
133+
}
134+
135+
private List<CPluginCustomization> readCustomizations(String fileName) {
136+
final List<CPluginCustomization> customizations = new LinkedList<CPluginCustomization>();
137+
DocumentBuilder documentBuilder = null;
138+
139+
try {
140+
documentBuilder = documentBuilderFactory.newDocumentBuilder();
141+
} catch (ParserConfigurationException pcex) {
142+
throw new UnsupportedOperationException("Could not created the DOM parser.", pcex);
143+
}
144+
145+
final File file = new File(getDirectory(), fileName);
146+
if (!file.exists()) {
147+
if (isVerbose()) {
148+
logger.debug(MessageFormat.format("File [{0}] does not exist.", file.getAbsolutePath()));
149+
}
150+
} else if (!file.isFile()) {
151+
logger.warn(MessageFormat.format("File [{0}] is not a file.", file.getAbsolutePath()));
152+
} else {
153+
InputStream is = null;
154+
try {
155+
is = new FileInputStream(file);
156+
final Document document = documentBuilder.parse(is);
157+
final Element documentElement = document.getDocumentElement();
158+
logger.debug(MessageFormat.format("Loaded customizations from [{0}].", file.getAbsolutePath()));
159+
final QName documentElementName = new QName(documentElement.getNamespaceURI(),
160+
documentElement.getLocalName());
161+
if (Customizations.CUSTOMIZATIONS_ELEMENT_NAME.equals(documentElementName)) {
162+
final NodeList childNodes = documentElement.getChildNodes();
163+
for (int index = 0; index < childNodes.getLength(); index++) {
164+
final Node childNode = childNodes.item(index);
165+
if (childNode.getNodeType() == Node.ELEMENT_NODE) {
166+
final Element childElement = (Element) childNode;
167+
customizations.add(new CPluginCustomization(childElement, null));
168+
}
169+
}
170+
} else {
171+
customizations.add(new CPluginCustomization(documentElement, null));
172+
}
173+
174+
} catch (IOException ioex) {
175+
logger.warn(MessageFormat.format("Could not parse [{0}].", file.getAbsolutePath()), ioex);
176+
} catch (SAXException saxex) {
177+
logger.warn(MessageFormat.format("Could not parse [{0}].", file.getAbsolutePath()), saxex);
178+
} finally {
179+
if (is != null) {
180+
try {
181+
is.close();
182+
} catch (IOException ignored) {
183+
}
184+
}
185+
}
186+
}
187+
return customizations;
188+
}
189+
}

basic/src/main/resources/META-INF/services/com.sun.tools.xjc.Plugin

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ org.jvnet.jaxb2_commons.plugin.simplify.SimplifyPlugin
1313
org.jvnet.jaxb2_commons.plugin.simplehashcode.SimpleHashCodePlugin
1414
org.jvnet.jaxb2_commons.plugin.simpleequals.SimpleEqualsPlugin
1515
org.jvnet.jaxb2_commons.plugin.enumvalue.EnumValuePlugin
16-
org.jvnet.jaxb2_commons.plugin.fixjaxb1058.FixJAXB1058Plugin
16+
org.jvnet.jaxb2_commons.plugin.fixjaxb1058.FixJAXB1058Plugin
17+
org.jvnet.jaxb2_commons.plugin.customizations.CustomizationsPlugin

tests/issues/pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@
4848
<arg>-XautoInheritance-jaxbElementsImplement=org.jvnet.jaxb2_commons.tests.issues.IssueJIIB14BaseInterfaceThree</arg>
4949
<arg>-XautoInheritance-jaxbElementsImplement=org.jvnet.jaxb2_commons.tests.issues.IssueJIIB14BaseInterfaceFour</arg>
5050
<arg>-XenumValue</arg>
51+
<arg>-Xcustomizations</arg>
52+
<arg>-Xcustomizations-directory=${basedir}/src/main/resources</arg>
53+
<arg>-Xcustomizations-verbose=true</arg>
5154
</args>
5255
<plugins>
5356
<plugin>

tests/issues/src/main/resources/binding.xjb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
jaxb:version="2.1">
88

99
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
10-
<jaxb:bindings node="xsd:simpleType[@name='issueJIIB38Type']">
11-
<inheritance:implements>java.lang.Cloneable</inheritance:implements>
12-
</jaxb:bindings>
1310
<jaxb:bindings node="xsd:element[@name='issueJIIB38']">
1411
<jaxb:class/>
1512
<inheritance:implements>java.lang.Cloneable</inheritance:implements>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<customizations:customizations xmlns:customizations="http://jaxb2-commons.dev.java.net/basic/customizations">
2+
<inheritance:implements xmlns:inheritance="http://jaxb2-commons.dev.java.net/basic/inheritance">java.lang.Cloneable</inheritance:implements>
3+
</customizations:customizations>

tools/src/main/java/org/jvnet/jaxb2_commons/util/ClassUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.sun.codemodel.JClass;
1010
import com.sun.codemodel.JDefinedClass;
1111
import com.sun.tools.xjc.model.CClassInfo;
12+
import com.sun.tools.xjc.model.CEnumLeafInfo;
1213
import com.sun.tools.xjc.outline.ClassOutline;
1314
import com.sun.tools.xjc.outline.FieldOutline;
1415

@@ -79,6 +80,20 @@ public static FieldOutline[] getFields(ClassOutline classOutline) {
7980
return fields.toArray(new FieldOutline[fields.size()]);
8081
}
8182

83+
public static String getPackagedClassName(final CEnumLeafInfo enumLeafInfo) {
84+
85+
if (enumLeafInfo.parent instanceof CClassInfo) {
86+
return getPackagedClassName((CClassInfo) enumLeafInfo.parent) + '$'
87+
+ enumLeafInfo.shortName;
88+
} else {
89+
final String r = enumLeafInfo.parent.fullName();
90+
if (r.length() == 0)
91+
return enumLeafInfo.shortName;
92+
else
93+
return r + '.' + enumLeafInfo.shortName;
94+
}
95+
}
96+
8297
public static String getPackagedClassName(final CClassInfo classInfo) {
8398

8499
if (classInfo.parent() instanceof CClassInfo) {

0 commit comments

Comments
 (0)