1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.directory.api.dsmlv2;
21
22
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.util.Collection;
26
27 import javax.xml.transform.Transformer;
28 import javax.xml.transform.TransformerConfigurationException;
29 import javax.xml.transform.TransformerException;
30 import javax.xml.transform.TransformerFactory;
31 import javax.xml.transform.stream.StreamSource;
32
33 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml;
34 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.Processing;
35 import org.apache.directory.api.dsmlv2.request.BatchRequestDsml.ResponseOrder;
36 import org.apache.directory.api.i18n.I18n;
37 import org.apache.directory.api.ldap.codec.api.CodecControl;
38 import org.apache.directory.api.ldap.codec.api.LdapApiService;
39 import org.apache.directory.api.ldap.model.entry.BinaryValue;
40 import org.apache.directory.api.ldap.model.entry.StringValue;
41 import org.apache.directory.api.ldap.model.ldif.LdifUtils;
42 import org.apache.directory.api.ldap.model.message.Control;
43 import org.apache.directory.api.util.Base64;
44 import org.apache.directory.api.util.Strings;
45 import org.dom4j.Document;
46 import org.dom4j.Element;
47 import org.dom4j.Namespace;
48 import org.dom4j.QName;
49 import org.dom4j.io.DocumentResult;
50 import org.dom4j.io.DocumentSource;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
53 import org.xmlpull.v1.XmlPullParser;
54 import org.xmlpull.v1.XmlPullParserException;
55
56
57
58
59
60
61
62 public final class ParserUtils
63 {
64
65 public static final String XML_SCHEMA_URI = "http://www.w3.org/2001/XMLSchema";
66
67
68 public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3.org/2001/XMLSchema-instance";
69
70
71 public static final String BASE64BINARY = "base64Binary";
72
73
74 public static final String XSI = "xsi";
75
76
77 public static final String XSD = "xsd";
78
79
80 public static final Namespace DSML_NAMESPACE = new Namespace( null, "urn:oasis:names:tc:DSML:2:0:core" );
81
82
83 public static final Namespace XSD_NAMESPACE = new Namespace( XSD, XML_SCHEMA_URI );
84
85
86 public static final Namespace XSI_NAMESPACE = new Namespace( XSI, XML_SCHEMA_INSTANCE_URI );
87
88
89 private static final Logger LOG = LoggerFactory.getLogger( ParserUtils.class );
90
91
92
93
94
95
96
97
98 public static String getXsiTypeAttributeValue( XmlPullParser xpp )
99 {
100 String type = null;
101 int nbAttributes = xpp.getAttributeCount();
102
103 for ( int i = 0; i < nbAttributes; i++ )
104 {
105
106 if ( xpp.getAttributeName( i ).equals( "type" )
107 && xpp.getNamespace( xpp.getAttributePrefix( i ) ).equals( XML_SCHEMA_INSTANCE_URI ) )
108 {
109 type = xpp.getAttributeValue( i );
110 break;
111 }
112 }
113
114 return type;
115 }
116
117
118
119
120
121
122
123
124
125 public static boolean isBase64BinaryValue( XmlPullParser parser, String attrValue )
126 {
127 if ( attrValue == null )
128 {
129 return false;
130 }
131
132
133
134 String[] splitedString = attrValue.split( ":" );
135
136 return ( splitedString.length == 2 ) && ( XML_SCHEMA_URI.equals( parser.getNamespace( splitedString[0] ) ) )
137 && ( BASE64BINARY.equals( splitedString[1] ) );
138 }
139
140
141
142
143
144
145
146
147 public static boolean needsBase64Encoding( Object value )
148 {
149 if ( value instanceof StringValue )
150 {
151 return false;
152 }
153 else if ( value instanceof BinaryValue )
154 {
155 return false;
156 }
157 else if ( value instanceof byte[] )
158 {
159 return true;
160 }
161 else if ( value instanceof String )
162 {
163 return !LdifUtils.isLDIFSafe( ( String ) value );
164 }
165
166 return true;
167 }
168
169
170
171
172
173
174
175
176 public static String base64Encode( Object value )
177 {
178 if ( value instanceof byte[] )
179 {
180 return new String( Base64.encode( ( byte[] ) value ) );
181 }
182 else if ( value instanceof String )
183 {
184 return new String( Base64.encode( Strings.getBytesUtf8( ( String ) value ) ) );
185 }
186
187 return "";
188 }
189
190
191
192
193
194
195
196
197
198
199 public static int parseAndVerifyRequestID( String attributeValue, XmlPullParser xpp ) throws XmlPullParserException
200 {
201 try
202 {
203 int requestID = Integer.parseInt( attributeValue );
204
205 if ( requestID < 0 )
206 {
207 throw new XmlPullParserException( I18n.err( I18n.ERR_03038, requestID ), xpp, null );
208 }
209
210 return requestID;
211 }
212 catch ( NumberFormatException e )
213 {
214 throw new XmlPullParserException( I18n.err( I18n.ERR_03039 ), xpp, null );
215 }
216 }
217
218
219
220
221
222
223
224
225 public static void addControls( LdapApiService codec, Element element, Collection<Control> controls )
226 {
227 if ( controls != null )
228 {
229 for ( Control control : controls )
230 {
231 Element controlElement = element.addElement( "control" );
232
233 if ( control.getOid() != null )
234 {
235 controlElement.addAttribute( "type", control.getOid() );
236 }
237
238 if ( control.isCritical() )
239 {
240 controlElement.addAttribute( "criticality", "true" );
241 }
242
243 byte[] value;
244
245 if ( control instanceof CodecControl<?> )
246 {
247 value = ( ( org.apache.directory.api.ldap.codec.api.CodecControl<?> ) control ).getValue();
248 }
249 else
250 {
251 value = codec.newControl( control ).getValue();
252 }
253
254 if ( value != null )
255 {
256 if ( ParserUtils.needsBase64Encoding( value ) )
257 {
258 element.getDocument().getRootElement().add( XSD_NAMESPACE );
259 element.getDocument().getRootElement().add( XSI_NAMESPACE );
260
261 Element valueElement = controlElement.addElement( "controlValue" ).addText(
262 ParserUtils.base64Encode( value ) );
263 valueElement.addAttribute( new QName( "type", XSI_NAMESPACE ), ParserUtils.XSD + ":"
264 + ParserUtils.BASE64BINARY );
265 }
266 else
267 {
268 controlElement.addElement( "controlValue" ).setText( Arrays.toString( value ) );
269 }
270 }
271 }
272 }
273 }
274
275
276
277
278
279
280
281
282
283 public static boolean isRequestIdNeeded( Dsmlv2Container container ) throws XmlPullParserException
284 {
285 BatchRequestDsml batchRequest = container.getBatchRequest();
286
287 if ( batchRequest == null )
288 {
289 throw new XmlPullParserException( I18n.err( I18n.ERR_03040 ), container.getParser(), null );
290 }
291
292 return ( ( batchRequest.getProcessing() == Processing.PARALLEL ) && ( batchRequest.getResponseOrder() == ResponseOrder.UNORDERED ) );
293 }
294
295
296
297
298
299
300
301
302 public static Document styleDocument( Document document )
303 {
304
305 TransformerFactory factory = TransformerFactory.newInstance();
306 Transformer transformer = null;
307
308 try
309 {
310 transformer = factory.newTransformer( new StreamSource( ParserUtils.class
311 .getResourceAsStream( "DSMLv2.xslt" ) ) );
312 }
313 catch ( TransformerConfigurationException e1 )
314 {
315 LOG.warn( "Failed to create the XSLT transformer", e1 );
316
317 return document;
318 }
319
320
321 DocumentSource source = new DocumentSource( document );
322 DocumentResult result = new DocumentResult();
323
324 try
325 {
326 transformer.transform( source, result );
327 }
328 catch ( TransformerException e )
329 {
330
331 return document;
332 }
333
334
335 Document transformedDoc = result.getDocument();
336 return transformedDoc;
337 }
338
339
340
341
342 public static final GrammarAction readSoapHeader = new GrammarAction( "Reads SOAP header" )
343 {
344 public void action( Dsmlv2Container container ) throws XmlPullParserException
345 {
346 try
347 {
348 XmlPullParser xpp = container.getParser();
349 StringBuilder sb = new StringBuilder();
350
351 String startTag = xpp.getText();
352 sb.append( startTag );
353
354
355 startTag = startTag.substring( 1, startTag.length() - 1 );
356
357 int tagType = -1;
358 String endTag = "";
359
360
361
362 while ( !startTag.equals( endTag ) )
363 {
364 tagType = xpp.next();
365 endTag = xpp.getText();
366 sb.append( endTag );
367
368 if ( tagType == XmlPullParser.END_TAG )
369 {
370
371 endTag = endTag.substring( 2, endTag.length() - 1 );
372 }
373 }
374
375
376 container.setState( Dsmlv2StatesEnum.SOAP_HEADER_END_TAG );
377 }
378 catch ( IOException e )
379 {
380 e.printStackTrace();
381 }
382
383 }
384 };
385
386 }