KickJava   Java API By Example, From Geeks To Geeks.

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


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

94 public class PostSyncML {
95
96     // --------------------------------------------------------------- Constants
97

98     public static String JavaDoc LOG_NAME = "sync4j.test.tools.PostSyncML";
99
100     public static String JavaDoc FILE_ERROR = "error" ;
101     public static String JavaDoc FILE_RESPONSE = "response" ;
102     public static String JavaDoc FILE_REFERENCE = "reference";
103
104     // ------------------------------------------------------------ Private data
105

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

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

153     public void syncAndTest() throws IOException, TestFailedException {
154         //
155
// First of all clean up!
156
//
157
clean();
158
159         SyncML response = null;
160         String JavaDoc respURI = null;
161         String JavaDoc referenceXML = null;
162
163         File responseFile = null;
164         for (int i=0; i<msgs.length; ++i) {
165
166             if (antTask != null) {
167                 log.info("Trying to execute task: " + msgFiles[i]);
168                 antTask.setTarget(msgFiles[i]);
169                 try {
170                     antTask.execute();
171                 } catch (BuildException ex) {
172                     //do nothing
173
}
174             }
175             
176             //
177
// Read ant properties
178
//
179
Properties JavaDoc prop = new Properties JavaDoc();
180             
181             File f = new File(baseDir, msgFiles[i] + ".properties");
182             if (f.exists()) {
183                 prop.load(new FileInputStream(f));
184             }
185             
186             String JavaDoc propertiesValues = prop.getProperty("replace");
187             
188             //
189
// Replace value_N into message before sending response
190
//
191
if (propertiesValues != null) {
192                 StringTokenizer JavaDoc values = new StringTokenizer JavaDoc(propertiesValues, ",");
193                 int y = 1;
194                 while (values.hasMoreTokens()) {
195                     String JavaDoc v = values.nextToken();
196                     msgs[i] = msgs[i].replaceAll("VALUE_" + y, v);
197                     y++;
198                 }
199             }
200
201             log.info("Sending " + msgFiles[i]);
202
203             try {
204                 response = postRequest(msgs[i]);
205             } catch (RepresentationException e) {
206                 IOTools.writeFile(e.getMessage(), new File(errorDir, msgFiles[i]));
207                 throw new TestFailedException ("XML syntax error: " + e.getMessage(), e);
208             } catch (Sync4jException e) {
209                 IOTools.writeFile(e.getMessage(), new File(errorDir, msgFiles[i]));
210                 throw new TestFailedException ("XML syntax error: " + e.getMessage(), e);
211             }
212
213             //
214
// Write the messages responded by the server, than read the reference
215
// and make the comparison (excluding the XPaths specified by
216
// ignoreXPaths
217
//
218
responseFile = new File(responseDir, msgFiles[i]);
219             log.info("Writing the response into " + responseFile);
220
221             try {
222
223                 String JavaDoc xmlMsg = marshallSyncML(response);
224                 IOTools.writeFile(xmlMsg, responseFile);
225
226             } catch(Exception JavaDoc e) {
227                 e.printStackTrace();
228                 throw new TestFailedException ("XML syntax error: " + e.getMessage(), e);
229             }
230
231             referenceXML = IOTools.readFileString(new File(referenceDir, msgFiles[i]));
232
233             compare(msgFiles[i]);
234
235             respURI = response.getSyncHdr().getRespURI();
236
237             if (respURI != null) {
238                 nextURL = respURI;
239             }
240         }
241     }
242
243     // --------------------------------------------------------- Private methods
244

245     private SyncML postRequest(String JavaDoc request)
246     throws IOException, Sync4jException, RepresentationException {
247         HttpClientConnection syncMLConnection = new HttpClientConnection(nextURL);
248         return syncMLConnection.sendMessage(request);
249     }
250
251     private void compare(String JavaDoc msgFile)
252     throws IOException, TestFailedException {
253         File responseFile = new File(responseDir , msgFile);
254         File referenceFile = new File(referenceDir, msgFile);
255
256         SAXBuilder sb = new SAXBuilder();
257         sb.setFactory(new DomFactory());
258
259         try {
260             Document response = sb.build(responseFile );
261             Document reference = sb.build(referenceFile);
262
263             OtaUpdate update = new OtaUpdate(false);
264
265             UniqueId id = new UniqueId("SyncMLTest", msgFile);
266             Element diffs = update.generateDiffs(response.getRootElement() ,
267                                                  reference.getRootElement(),
268                                                  id );
269
270             if (log.isLoggable(Level.FINEST)) {
271                 saveDiffs(diffs, new File(errorDir, msgFile + ".dbg"));
272             }
273
274             if (checkDiffs(diffs)) {
275                 saveDiffs(diffs, new File(errorDir, msgFile));
276
277                 throw new TestFailedException( "Test failed on "
278                                              + msgFile
279                                              + ". Diff file saved in "
280                                              + new File(errorDir, msgFile)
281                                              );
282             }
283         } catch (JDOMException e) {
284             IOTools.writeFile(e.getMessage(), new File(errorDir, msgFile));
285             throw new TestFailedException("Test failed on "
286                                              + msgFile
287                                              + ": "
288                                              + e.getMessage()
289                                              + ". Error message saved in "
290                                              + new File(errorDir, msgFile)
291                                              );
292         }
293     }
294
295     /**
296      * Checks if the given diffs Element contains significant differences, so
297      * that differences on any node excluding the ones specified by the
298      * <i>ignoreXPaths</i> XPaths.
299      *
300      * @param diffs the differences to be inspected
301      *
302      * @return <i>true</i> if there is at least one difference in one of the not
303      * ignored XPaths, or <i>false</i> otherwise.
304      */

305     private boolean checkDiffs(Element diffs) {
306         List JavaDoc positions = diffs.getChildren("Position", diffs.getNamespace());
307
308         Element position = null;
309
310         Iterator JavaDoc i = positions.iterator();
311         while(i.hasNext()) {
312             position = (Element)i.next();
313
314             if (!ignore(position.getAttributeValue("XPath"))) {
315                 //
316
// This means a difference!
317
//
318
return true;
319             }
320         }
321
322         return false;
323     }
324
325     /**
326      * Removes old files from the working directories
327      */

328     private void clean() {
329         FilenameFilter filter = IOTools.getFileTypeFilter("xml");
330
331         String JavaDoc[] files = responseDir.list(filter);
332
333         for (int i=0; ((files != null) && (i<files.length)); ++i) {
334             new File(files[i]).delete();
335         }
336
337         files = errorDir.list(filter);
338
339         for (int i=0; ((files != null) && (i<files.length)); ++i) {
340             new File(files[i]).delete();
341         }
342     }
343
344     /**
345      * Checks if the given XPath is one of the ignored XPath
346      *
347      * @param xPath the xPath to check
348      *
349      * @return <i>true</i> is the xPath in the list of the ignored XPaths,
350      * <i>false</i> otherwise.
351      */

352     private boolean ignore(String JavaDoc xPath) {
353
354         for (int i=0;
355              ((xPath != null) && (ignoreXPaths != null) && (i<ignoreXPaths.length));
356              ++i) {
357             if (xPath.equals(ignoreXPaths[i])) {
358                 return true;
359             }
360         }
361
362         return false;
363     }
364
365     /**
366      * Saves the given diff element to the given file
367      *
368      * @param diffs the diff element
369      * @param file the file to save into
370      */

371     private void saveDiffs(Element diffs, File file) throws IOException {
372         XMLOutputter xmlo = new XMLOutputter(" ", true);
373         xmlo.setTextNormalize(true);
374
375         FileOutputStream fos = new FileOutputStream(file);
376         xmlo.output(diffs, fos);
377         fos.close();
378     }
379
380     private static void syntax() {
381         System.out.println("Syntax: " + (PostSyncML.class) + "<initial URL> <msg1> ... <msgN>");
382     }
383
384     private String JavaDoc marshallSyncML(SyncML syncML) throws Sync4jException {
385         String JavaDoc msg = null;
386         try {
387
388             ByteArrayOutputStream bout = new ByteArrayOutputStream();
389
390             IBindingFactory f = BindingDirectory.getFactory(SyncML.class);
391             IMarshallingContext c = f.createMarshallingContext();
392             c.setIndent(0);
393             c.marshalDocument(syncML, "UTF-8", null, bout);
394             msg = new String JavaDoc(bout.toByteArray());
395
396         } catch(Exception JavaDoc e) {
397             e.printStackTrace();
398             throw new Sync4jException(e);
399         }
400         return msg;
401     }
402     // -------------------------------------------------------------------- Main
403

404     public static void main(String JavaDoc args[])
405     throws Exception JavaDoc {
406         if(args.length < 2) {
407             syntax();
408         }
409
410         String JavaDoc[] msgFiles = new String JavaDoc[args.length-1];
411
412         System.arraycopy(args, 1, msgFiles, 0, msgFiles.length);
413
414         PostSyncML postsyncml = new PostSyncML(args[0], new File("."), msgFiles, new String JavaDoc[0], null);
415         postsyncml.syncAndTest();
416     }
417 }
418
Popular Tags