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.w3c.org/2001/XMLSchema";
66
67
68 public static final String XML_SCHEMA_INSTANCE_URI = "http://www.w3c.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 public static String getXsiTypeAttributeValue( XmlPullParser xpp )
98 {
99 String type = null;
100 int nbAttributes = xpp.getAttributeCount();
101
102 for ( int i = 0; i < nbAttributes; i++ )
103 {
104
105 if ( xpp.getAttributeName( i ).equals( "type" )
106 && xpp.getNamespace( xpp.getAttributePrefix( i ) ).equals( XML_SCHEMA_INSTANCE_URI ) )
107 {
108 type = xpp.getAttributeValue( i );
109 break;
110 }
111 }
112
113 return type;
114 }
115
116
117
118
119
120
121
122
123
124 public static boolean isBase64BinaryValue( XmlPullParser parser, String attrValue )
125 {
126 if ( attrValue == null )
127 {
128 return false;
129 }
130
131
132
133 String[] splitedString = attrValue.split( ":" );
134
135 return ( splitedString.length == 2 ) && ( XML_SCHEMA_URI.equals( parser.getNamespace( splitedString[0] ) ) )
136 && ( BASE64BINARY.equals( splitedString[1] ) );
137 }
138
139
140
141
142
143
144
145
146 public static boolean needsBase64Encoding( Object value )
147 {
148 if ( value instanceof StringValue )
149 {
150 return false;
151 }
152 else if ( value instanceof BinaryValue )
153 {
154 return false;
155 }
156 else if ( value instanceof byte[] )
157 {
158 return true;
159 }
160 else if ( value instanceof String )
161 {
162 return !LdifUtils.isLDIFSafe( ( String ) value );
163 }
164
165 return true;
166 }
167
168
169
170
171
172
173
174
175 public static String base64Encode( Object value )
176 {
177 if ( value instanceof byte[] )
178 {
179 return new String( Base64.encode( ( byte[] ) value ) );
180 }
181 else if ( value instanceof String )
182 {
183 return new String( Base64.encode( Strings.getBytesUtf8( ( String ) value ) ) );
184 }
185
186 return "";
187 }
188
189
190
191
192
193
194
195
196
197
198 public static int parseAndVerifyRequestID( String attributeValue, XmlPullParser xpp ) throws XmlPullParserException
199 {
200 try
201 {
202 int requestID = Integer.parseInt( attributeValue );
203
204 if ( requestID < 0 )
205 {
206 throw new XmlPullParserException( I18n.err( I18n.ERR_03038, requestID ), xpp, null );
207 }
208
209 return requestID;
210 }
211 catch ( NumberFormatException e )
212 {
213 throw new XmlPullParserException( I18n.err( I18n.ERR_03039 ), xpp, null );
214 }
215 }
216
217
218
219
220
221
222
223
224 public static void addControls( LdapApiService codec, Element element, Collection<Control> controls )
225 {
226 if ( controls != null )
227 {
228 for ( Control control : controls )
229 {
230 Element controlElement = element.addElement( "control" );
231
232 if ( control.getOid() != null )
233 {
234 controlElement.addAttribute( "type", control.getOid() );
235 }
236
237 if ( control.isCritical() )
238 {
239 controlElement.addAttribute( "criticality", "true" );
240 }
241
242 byte[] value;
243
244 if ( control instanceof CodecControl<?> )
245 {
246 value = ( ( org.apache.directory.api.ldap.codec.api.CodecControl<?> ) control ).getValue();
247 }
248 else
249 {
250 value = codec.newControl( control ).getValue();
251 }
252
253 if ( value != null )
254 {
255 if ( ParserUtils.needsBase64Encoding( value ) )
256 {
257 element.getDocument().getRootElement().add( XSD_NAMESPACE );
258 element.getDocument().getRootElement().add( XSI_NAMESPACE );
259
260 Element valueElement = controlElement.addElement( "controlValue" ).addText(
261 ParserUtils.base64Encode( value ) );
262 valueElement.addAttribute( new QName( "type", XSI_NAMESPACE ), ParserUtils.XSD + ":"
263 + ParserUtils.BASE64BINARY );
264 }
265 else
266 {
267 controlElement.addElement( "controlValue" ).setText( Arrays.toString( value ) );
268 }
269 }
270 }
271 }
272 }
273
274
275
276
277
278
279
280
281
282 public static boolean isRequestIdNeeded( Dsmlv2Container container ) throws XmlPullParserException
283 {
284 BatchRequestDsml batchRequest = container.getBatchRequest();
285
286 if ( batchRequest == null )
287 {
288 throw new XmlPullParserException( I18n.err( I18n.ERR_03040 ), container.getParser(), null );
289 }
290
291 return ( ( batchRequest.getProcessing() == Processing.PARALLEL ) && ( batchRequest.getResponseOrder() == ResponseOrder.UNORDERED ) );
292 }
293
294
295
296
297
298
299
300
301 public static Document styleDocument( Document document )
302 {
303
304 TransformerFactory factory = TransformerFactory.newInstance();
305 Transformer transformer = null;
306
307 try
308 {
309 transformer = factory.newTransformer( new StreamSource( ParserUtils.class
310 .getResourceAsStream( "DSMLv2.xslt" ) ) );
311 }
312 catch ( TransformerConfigurationException e1 )
313 {
314 LOG.warn( "Failed to create the XSLT transformer", e1 );
315
316 return document;
317 }
318
319
320 DocumentSource source = new DocumentSource( document );
321 DocumentResult result = new DocumentResult();
322
323 try
324 {
325 transformer.transform( source, result );
326 }
327 catch ( TransformerException e )
328 {
329
330 return document;
331 }
332
333
334 Document transformedDoc = result.getDocument();
335 return transformedDoc;
336 }
337
338
339
340
341 public static final GrammarAction readSoapHeader = new GrammarAction( "Reads SOAP header" )
342 {
343 public void action( Dsmlv2Container container ) throws XmlPullParserException
344 {
345 try
346 {
347 XmlPullParser xpp = container.getParser();
348 StringBuilder sb = new StringBuilder();
349
350 String startTag = xpp.getText();
351 sb.append( startTag );
352
353
354 startTag = startTag.substring( 1, startTag.length() - 1 );
355
356 int tagType = -1;
357 String endTag = "";
358
359
360
361 while ( !startTag.equals( endTag ) )
362 {
363 tagType = xpp.next();
364 endTag = xpp.getText();
365 sb.append( endTag );
366
367 if ( tagType == XmlPullParser.END_TAG )
368 {
369
370 endTag = endTag.substring( 2, endTag.length() - 1 );
371 }
372 }
373
374
375 container.setState( Dsmlv2StatesEnum.SOAP_HEADER_END_TAG );
376 }
377 catch ( IOException e )
378 {
379 e.printStackTrace();
380 }
381
382 }
383 };
384
385 }