KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > sync4j > test > tools > PostWBXMLSyncML


1 /**
2  * Copyright (C) 2003-2005 Funambol
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  */

18 package sync4j.test.tools;
19
20 import java.net.*;
21 import java.io.*;
22 import java.util.List JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.logging.Logger JavaDoc;
25 import java.util.logging.Level JavaDoc;
26
27 import org.jdom.*;
28 import org.jdom.input.SAXBuilder;
29 import org.jdom.output.XMLOutputter;
30
31 import org.vmguys.vmtools.ota.OtaUpdate;
32 import org.vmguys.vmtools.ota.UniqueId;
33 import org.vmguys.vmtools.utils.DomFactory;
34
35 import org.apache.tools.ant.*;
36 import org.apache.tools.ant.taskdefs.*;
37
38 import sync4j.framework.core.*;
39 import sync4j.framework.protocol.*;
40 import sync4j.framework.tools.IOTools;
41 import sync4j.framework.tools.WBXMLTools;
42
43 import sync4j.test.tools.HttpClientConnection;
44 import sync4j.test.TestFailedException;
45
46
47 /**
48  * This is a driver for running tests at the protocol level.
49  * It requires a directory structure like this:
50  * <pre>
51  * {test code}
52  * <i>msg1.xml</i>
53  * <i>msg2.xml</i>
54  * <i>...</i>
55  * reference
56  * <i>msg1.xml</i>
57  * <i>msg2.xml</i>
58  * <i>...</i>
59  * response
60  * <i>msg1.xml</i>
61  * <i>msg2.xml</i>
62  * <i>...</i>
63  * </pre>
64  * <i>test code</i> is the code name of the test to be performed (i.e. WOSI0001);
65  * msg{N}.xml are the messages that the client has to send to the server. For
66  * each message sent, the response is stored in the <i>response</i> directory.
67  * <p>
68  * The directory <i>reference</i> contains the expected response messages used
69  * by the comparison tool to identify the differences between the returned
70  * messages and the expected values.
71  * <p>
72  * This class is designe to work as a standalone program. An Ant task is
73  * developed as well; @see sync4j.test.tools.ant.PostSyncMLTask .
74  * <p>
75  * <b>Syntax</b>
76  * <pre>
77  * sync4j.test.tools.PostSyncML {initial URL} {file msg1} ... {file msgN}
78  *
79  * where:
80  *
81  * {initial URL}: the URL the first request has to be sent to (the others depend
82  * by the RespURI element in the response.
83  * {file msg1} .. {file msgN}: the messages to send to server. They are sent in
84  * the order they appear on the command line.
85  * </pre>
86  *
87  * @author Stefano Fornari
88  * @version $Id: PostWBXMLSyncML.java,v 1.9 2005/05/16 07:28:47 luigiafassina Exp $
89  */

90 public class PostWBXMLSyncML {
91
92     // --------------------------------------------------------------- Constants
93

94     public static String JavaDoc LOG_NAME = "sync4j.test.tools.PostSyncML";
95
96     public static String JavaDoc FILE_ERROR = "error" ;
97     public static String JavaDoc FILE_RESPONSE = "response" ;
98     public static String JavaDoc FILE_REFERENCE = "reference";
99
100     // ------------------------------------------------------------ Private data
101

102     private CommandIdGenerator idGenerator = null;
103     private String JavaDoc nextURL = null;
104     private byte[][] msgs = null;
105     private String JavaDoc[] msgFiles = null;
106     private String JavaDoc[] ignoreXPaths = null;
107
108     private Ant antTask = null;
109
110     private File baseDir = null;
111     private File responseDir = null, referenceDir = null, errorDir = null;
112
113     private static final Logger JavaDoc log = Logger.getLogger(LOG_NAME);
114
115     // ------------------------------------------------------------ Constructors
116

117     public PostWBXMLSyncML(String JavaDoc initialURL ,
118                            File baseDir ,
119                            String JavaDoc[] msgFiles ,
120                            String JavaDoc[] ignoreXPaths,
121                            Ant antTask)
122     throws IOException {
123         idGenerator = new CommandIdGenerator();
124
125         if ((msgFiles == null) || (msgFiles.length == 0)) {
126             msgs = new byte[0][];
127         }
128
129         msgs = new byte[msgFiles.length][];
130
131         this.baseDir = baseDir;
132         this.responseDir = new File(baseDir, FILE_RESPONSE );
133         this.referenceDir = new File(baseDir, FILE_REFERENCE);
134         this.errorDir = new File(baseDir, FILE_ERROR );
135
136         this.msgFiles = msgFiles;
137         for (int i=0; i<msgFiles.length; ++i) {
138             msgs[i] = IOTools.readFileBytes(new File(baseDir, msgFiles[i]));
139         }
140
141         this.ignoreXPaths = ignoreXPaths;
142         this.antTask = antTask;
143
144         nextURL = initialURL;
145     }
146
147     //----------------------------------------------------------- Public methods
148

149     public void syncAndTest() throws IOException, TestFailedException {
150         //
151
// First of all clean up!
152
//
153
clean();
154
155         SyncML response = null;
156         String JavaDoc respURI = null;
157
158         String JavaDoc referenceXML = null;
159
160         File responseFile = null;
161         for (int i=0; i<msgs.length; ++i) {
162
163             if (antTask != null) {
164                 log.info("Trying to execute task: " + msgFiles[i]);
165                 antTask.setTarget(msgFiles[i]);
166                 try {
167                     antTask.execute();
168                 } catch (BuildException ex) {
169                     //do nothing
170
}
171             }
172
173             log.info("Sending " + msgFiles[i]);
174
175             try {
176                 response = postRequest(msgs[i]);
177             } catch (RepresentationException e) {
178                 IOTools.writeFile(e.getMessage(), new File(errorDir, msgFiles[i]));
179                 throw new TestFailedException ("XML syntax error: " + e.getMessage(), e);
180             } catch (Sync4jException e) {
181                 IOTools.writeFile(e.getMessage(), new File(errorDir, msgFiles[i]));
182                 throw new TestFailedException ("XML syntax error: " + e.getMessage(), e);
183             }
184
185             //
186
// Write the messages responded by the server, than read the reference
187
// and make the comparison (excluding the XPaths specified by
188
// ignoreXPaths
189
//
190
responseFile = new File(responseDir, msgFiles[i]);
191             log.info("Writing the response into " + responseFile);
192
193             try {
194                 IOTools.writeFile(WBXMLTools.toWBXML(response), responseFile);
195                 referenceXML = WBXMLTools.wbxmlToXml(IOTools.readFileBytes(new File(referenceDir, msgFiles[i])));
196                 compare(msgFiles[i]);
197             } catch (Sync4jException e) {
198                 IOTools.writeFile(e.getMessage(), new File(errorDir, msgFiles[i]));
199                 throw new TestFailedException ("WBXML error: " + e.getMessage(), e);
200             }
201
202             respURI = response.getSyncHdr().getRespURI();
203
204             if (respURI != null) {
205                 nextURL = respURI;
206             }
207         }
208     }
209
210     // --------------------------------------------------------- Private methods
211

212     private SyncML postRequest(byte[] request)
213     throws IOException, Sync4jException, RepresentationException {
214         HttpClientConnection syncMLConnection = new HttpClientConnection(nextURL);
215         return syncMLConnection.sendWBXMLMessage(request);
216     }
217
218     private void compare(String JavaDoc msgFile)
219     throws IOException, Sync4jException, TestFailedException {
220         File responseFile = new File(responseDir , msgFile);
221         File referenceFile = new File(referenceDir, msgFile);
222
223         //build reference/response from XML strings, NOT from the files (which contain WBXML)
224
String JavaDoc responseXml = WBXMLConverter.readWbxmlAsXml(responseFile);
225         String JavaDoc referenceXml = WBXMLConverter.readWbxmlAsXml(referenceFile);
226
227         StringReader responseReader = new StringReader(responseXml);
228         StringReader referenceReader = new StringReader(referenceXml);
229
230         SAXBuilder sb = new SAXBuilder();
231         sb.setFactory(new DomFactory());
232
233         try {
234             Document response = sb.build(responseReader);
235             Document reference = sb.build(referenceReader);
236
237             OtaUpdate update = new OtaUpdate(false);
238
239             UniqueId id = new UniqueId("SyncMLTest", msgFile);
240             Element diffs = update.generateDiffs(response.getRootElement() ,
241                                                  reference.getRootElement(),
242                                                  id );
243
244             if (log.isLoggable(Level.FINEST)) {
245                 saveDiffs(diffs, new File(errorDir, msgFile + ".dbg"));
246             }
247
248             if (checkDiffs(diffs)) {
249                 saveDiffs(diffs, new File(errorDir, msgFile));
250
251                 throw new TestFailedException( "Test failed on "
252                                              + msgFile
253                                              + ". Diff file saved in "
254                                              + new File(errorDir, msgFile)
255                                              );
256             }
257         } catch (JDOMException e) {
258             IOTools.writeFile(e.getMessage(), new File(errorDir, msgFile));
259             throw new TestFailedException("Test failed on "
260                                              + msgFile
261                                              + ": "
262                                              + e.getMessage()
263                                              + ". Error message saved in "
264                                              + new File(errorDir, msgFile)
265                                              );
266         }
267     }
268
269     /**
270      * Checks if the given diffs Element contains significant differences, so
271      * that differences on any node excluding the ones specified by the
272      * <i>ignoreXPaths</i> XPaths.
273      *
274      * @param diffs the differences to be inspected
275      *
276      * @return <i>true</i> if there is at least one difference in one of the not
277      * ignored XPaths, or <i>false</i> otherwise.
278      */

279     private boolean checkDiffs(Element diffs) {
280         List JavaDoc positions = diffs.getChildren("Position", diffs.getNamespace());
281
282         Element position = null;
283
284         Iterator JavaDoc i = positions.iterator();
285         while(i.hasNext()) {
286             position = (Element)i.next();
287
288             if (!ignore(position.getAttributeValue("XPath"))) {
289                 //
290
// This means a difference!
291
//
292
return true;
293             }
294         }
295
296         return false;
297     }
298
299     /**
300      * Removes old files from the working directories
301      */

302     private void clean() {
303         FilenameFilter filter = IOTools.getFileTypeFilter("wbxml");
304
305         String JavaDoc[] files = responseDir.list(filter);
306
307         for (int i=0; ((files != null) && (i<files.length)); ++i) {
308             new File(files[i]).delete();
309         }
310
311         files = errorDir.list(filter);
312
313         for (int i=0; ((files != null) && (i<files.length)); ++i) {
314             new File(files[i]).delete();
315         }
316     }
317
318     /**
319      * Checks if the given XPath is one of the ignored XPath
320      *
321      * @param xPath the xPath to check
322      *
323      * @return <i>true</i> is the xPath in the list of the ignored XPaths,
324      * <i>false</i> otherwise.
325      */

326     private boolean ignore(String JavaDoc xPath) {
327
328         for (int i=0;
329              ((xPath != null) && (ignoreXPaths != null) && (i<ignoreXPaths.length));
330              ++i) {
331             if (xPath.equals(ignoreXPaths[i])) {
332                 return true;
333             }
334         }
335
336         return false;
337     }
338
339     /**
340      * Saves the given diff element to the given file
341      *
342      * @param diffs the diff element
343      * @param file the file to save into
344      */

345     private void saveDiffs(Element diffs, File file) throws IOException {
346         XMLOutputter xmlo = new XMLOutputter(" ", true);
347         xmlo.setTextNormalize(true);
348
349         FileOutputStream fos = new FileOutputStream(file);
350         xmlo.output(diffs, fos);
351         fos.close();
352     }
353
354     private static void syntax() {
355         System.out.println("Syntax: " + (PostSyncML.class) + "<initial URL> <msg1> ... <msgN>");
356     }
357
358     // -------------------------------------------------------------------- Main
359

360     public static void main(String JavaDoc args[])
361     throws Exception JavaDoc {
362         if(args.length < 2) {
363             syntax();
364         }
365
366         String JavaDoc[] msgFiles = new String JavaDoc[args.length-1];
367
368         System.arraycopy(args, 1, msgFiles, 0, msgFiles.length);
369
370         PostWBXMLSyncML postsyncml = new PostWBXMLSyncML(args[0], new File("."), msgFiles, new String JavaDoc[0], null);
371         postsyncml.syncAndTest();
372     }
373 }
374
Popular Tags