1616
1717package org .springframework .xml .xsd .commons ;
1818
19+ import java .io .IOException ;
1920import java .util .ArrayList ;
2021import java .util .List ;
2122
22- import org .apache .commons .logging .Log ;
23- import org .apache .commons .logging .LogFactory ;
23+ import org .apache .ws .commons .schema .ValidationEventHandler ;
2424import org .apache .ws .commons .schema .XmlSchema ;
2525import org .apache .ws .commons .schema .XmlSchemaCollection ;
26- import org .apache .ws .commons .schema .constants .Constants ;
26+ import org .apache .ws .commons .schema .XmlSchemaExternal ;
27+ import org .apache .ws .commons .schema .XmlSchemaImport ;
28+ import org .apache .ws .commons .schema .XmlSchemaInclude ;
29+ import org .apache .ws .commons .schema .XmlSchemaObject ;
30+ import org .apache .ws .commons .schema .XmlSchemaObjectCollection ;
2731
2832import org .springframework .beans .factory .InitializingBean ;
2933import org .springframework .core .io .Resource ;
3438
3539/**
3640 * Implementation of the {@link XsdSchemaCollection} that uses Apache WS-Commons XML Schema.
41+ * <p/>
42+ * Setting the {@link #setInline(boolean) inline} flag to <code>true</code> will result in all referenced schemas
43+ * (included and imported) being merged into the referred schema. When including the schemas into a WSDL, this greatly
44+ * simplifies the deloyment of the schemas.
3745 *
3846 * @author Arjen Poutsma
3947 * @see <a href="http://ws.apache.org/commons/XmlSchema/">Commons XML Schema</a>
4048 * @since 1.5.0
4149 */
4250public class CommonsXsdSchemaCollection implements XsdSchemaCollection , InitializingBean {
4351
44- private static final Log logger = LogFactory .getLog (CommonsXsdSchemaCollection .class );
45-
4652 private final XmlSchemaCollection schemaCollection = new XmlSchemaCollection ();
4753
4854 private final List xmlSchemas = new ArrayList ();
4955
5056 private Resource [] xsdResources ;
5157
52- private boolean inlineIncludes = false ;
58+ private boolean inline = false ;
59+
60+ private ValidationEventHandler validationEventHandler ;
5361
5462 /**
5563 * Constructs a new, empty instance of the <code>CommonsXsdSchemaCollection</code>.
@@ -82,15 +90,26 @@ public void setXsds(Resource[] xsdResources) {
8290 * <p/>
8391 * Defaults to <code>false</code>.
8492 */
85- public void setInlineIncludes (boolean inlineIncludes ) {
86- this .inlineIncludes = inlineIncludes ;
93+ public void setInline (boolean inline ) {
94+ this .inline = inline ;
8795 }
8896
89- public void afterPropertiesSet () throws Exception {
97+ /** Sets the WS-Commons validation event handler to use while parsing schemas. */
98+ public void setValidationEventHandler (ValidationEventHandler validationEventHandler ) {
99+ this .validationEventHandler = validationEventHandler ;
100+ }
101+
102+ public void afterPropertiesSet () throws IOException {
90103 Assert .notEmpty (xsdResources , "'xsds' must not be empty" );
91104 for (int i = 0 ; i < xsdResources .length ; i ++) {
92105 Assert .isTrue (xsdResources [i ].exists (), xsdResources [i ] + " does not exit" );
93- xmlSchemas .add (schemaCollection .read (SaxUtils .createInputSource (xsdResources [i ]), null ));
106+ XmlSchema xmlSchema =
107+ schemaCollection .read (SaxUtils .createInputSource (xsdResources [i ]), validationEventHandler );
108+ xmlSchemas .add (xmlSchema );
109+ if (inline ) {
110+ inlineIncludes (xmlSchema , new ArrayList ());
111+ findImports (xmlSchema , new ArrayList ());
112+ }
94113 }
95114 }
96115
@@ -103,16 +122,55 @@ public XsdSchema[] getXsdSchemas() {
103122 return result ;
104123 }
105124
125+ private void inlineIncludes (XmlSchema schema , List processedSchemas ) {
126+ processedSchemas .add (schema );
127+ XmlSchemaObjectCollection includes = schema .getIncludes ();
128+ for (int i = 0 ; i < includes .getCount (); i ++) {
129+ XmlSchemaExternal external = (XmlSchemaExternal ) includes .getItem (i );
130+ if (external instanceof XmlSchemaInclude ) {
131+ XmlSchema includedSchema = external .getSchema ();
132+ XmlSchemaObjectCollection items = schema .getItems ();
133+ if (!processedSchemas .contains (includedSchema )) {
134+ inlineIncludes (includedSchema , processedSchemas );
135+ findImports (includedSchema , new ArrayList ());
136+ XmlSchemaObjectCollection includeItems = includedSchema .getItems ();
137+ for (int j = 0 ; j < includeItems .getCount (); j ++) {
138+ XmlSchemaObject includedItem = includeItems .getItem (j );
139+ items .add (includedItem );
140+ }
141+ }
142+ // remove the <include/>
143+ items .remove (external );
144+ }
145+ }
146+ }
147+
148+ private void findImports (XmlSchema schema , List processedSchemas ) {
149+ processedSchemas .add (schema );
150+ XmlSchemaObjectCollection includes = schema .getIncludes ();
151+ for (int i = 0 ; i < includes .getCount (); i ++) {
152+ XmlSchemaExternal external = (XmlSchemaExternal ) includes .getItem (i );
153+ if (external instanceof XmlSchemaImport ) {
154+ XmlSchema importedSchema = external .getSchema ();
155+ if (!processedSchemas .contains (importedSchema )) {
156+ inlineIncludes (importedSchema , processedSchemas );
157+ findImports (importedSchema , processedSchemas );
158+ xmlSchemas .add (importedSchema );
159+ }
160+ // remove the schemaLocation
161+ external .setSchemaLocation (null );
162+ }
163+ }
164+ }
165+
106166 public String toString () {
107167 StringBuffer buffer = new StringBuffer ("CommonsXsdSchemaCollection" );
108168 buffer .append ('{' );
109- XmlSchema [] schemas = schemaCollection .getXmlSchemas ();
110- for (int i = 0 ; i < schemas .length ; i ++) {
111- if (!Constants .URI_2001_SCHEMA_XSD .equals (schemas [i ].getTargetNamespace ())) {
112- buffer .append (schemas [i ].getTargetNamespace ());
113- if (i < schemas .length - 1 ) {
114- buffer .append (',' );
115- }
169+ for (int i = 0 ; i < xmlSchemas .size (); i ++) {
170+ XmlSchema schema = (XmlSchema ) xmlSchemas .get (i );
171+ buffer .append (schema .getTargetNamespace ());
172+ if (i < xmlSchemas .size () - 1 ) {
173+ buffer .append (',' );
116174 }
117175 }
118176 buffer .append ('}' );
0 commit comments