View Javadoc

1   package org.xvsm.remote.marshaller;
2   
3   import java.io.ByteArrayInputStream;
4   import java.io.ByteArrayOutputStream;
5   import java.io.OutputStream;
6   import java.lang.reflect.Constructor;
7   import java.net.URI;
8   import java.net.URISyntaxException;
9   import java.util.ArrayList;
10  import java.util.List;
11  import java.util.Properties;
12  
13  import javax.xml.stream.XMLInputFactory;
14  import javax.xml.stream.XMLOutputFactory;
15  import javax.xml.stream.XMLStreamConstants;
16  import javax.xml.stream.XMLStreamException;
17  import javax.xml.stream.XMLStreamReader;
18  import javax.xml.stream.XMLStreamWriter;
19  
20  import org.apache.log4j.Logger;
21  import org.xvsm.core.AtomicEntry;
22  import org.xvsm.core.ContainerRef;
23  import org.xvsm.core.Entry;
24  import org.xvsm.core.ExceptionEntry;
25  import org.xvsm.core.Tuple;
26  import org.xvsm.core.VoidEntry;
27  import org.xvsm.core.aspect.GlobalIPoint;
28  import org.xvsm.core.aspect.IAspect;
29  import org.xvsm.core.aspect.IPoint;
30  import org.xvsm.core.aspect.LocalIPoint;
31  import org.xvsm.core.notifications.NotificationAspect;
32  import org.xvsm.interfaces.ICoordinator;
33  import org.xvsm.internal.exceptions.FatalException;
34  import org.xvsm.internal.tasks.AspectTask;
35  import org.xvsm.internal.tasks.AspectTaskType;
36  import org.xvsm.internal.tasks.ClearTask;
37  import org.xvsm.internal.tasks.ContainerTask;
38  import org.xvsm.internal.tasks.ContainerTaskType;
39  import org.xvsm.internal.tasks.OperationTask;
40  import org.xvsm.internal.tasks.OperationTaskType;
41  import org.xvsm.internal.tasks.ShutdownTask;
42  import org.xvsm.internal.tasks.Task;
43  import org.xvsm.internal.tasks.TransactionTask;
44  import org.xvsm.internal.tasks.TransactionTaskType;
45  import org.xvsm.remote.interfaces.IMarshaller;
46  import org.xvsm.selectors.Selector;
47  import org.xvsm.transactions.Transaction;
48  
49  public class XMLMarshaller implements IMarshaller<byte[]> {
50  
51  	private static Logger logger = Logger.getLogger(XMLMarshaller.class);
52  
53  	private static String NAMESPACEURI = "http://www.xvsm.org";
54  
55  	// public static void main(String[] args) throws Exception {
56  	//
57  	// try {
58  	// LocalIPoint p = LocalIPoint.valueOf("PreTransactionCommit");
59  	// } catch (IllegalArgumentException e) {
60  	// GlobalIPoint p = GlobalIPoint.valueOf("PreTransactionCommit");
61  	// }
62  	// Transaction tx = new Transaction("andfih");
63  	// tx.setSite(new URI("tcpxml://locahost:9876"));
64  	//
65  	// Selector selectors[] = {
66  	// new RandomSelector(),
67  	// new FifoSelector(),
68  	// new GenericKeySelector<String>("Sepp", "Meier"),
69  	// new GenericKeySelector<Integer>("lalala", 1232),
70  	// new LindaSelector(new Tuple(new AtomicEntry<String>("eins"),
71  	// new AtomicEntry<String>("zwei"))),
72  	// new VectorSelector(1, 1) };
73  	// Entry entries[] = {
74  	// new AtomicEntry<String>("124"),
75  	// new AtomicEntry<Integer>(123),
76  	// new Tuple(new AtomicEntry<String>("eins"),
77  	// new AtomicEntry<String>("zwei")),
78  	// new Tuple(new Tuple(new AtomicEntry<Boolean>(true),
79  	// new AtomicEntry<Boolean>(false)),
80  	// new AtomicEntry<String>("XXXX")),
81  	// new Tuple(new Tuple(new AtomicEntry<Boolean>(true), null,
82  	// new AtomicEntry<String>("XXXX"))),
83  	// new Tuple(new Tuple(new AtomicEntry<Boolean>(true),
84  	// new AtomicEntry<String>("XXXX")), new Tuple(
85  	// (Entry) null)) };
86  	// ContainerRef notifContainer = new ContainerRef(new URI(
87  	// "tcpXML://localhost/XjtnotificationContainerID"));
88  	// notifContainer.setSite(new URI("example.com"));
89  	// Task[] tasks = new Task[] {
90  	// new ClearTask(),
91  	// new ContainerTask(tx, ContainerTaskType.CREATE, -1,
92  	// new FifoCoordinator(), new KeyCoordinator(new KeyType(
93  	// "name", String.class))),
94  	// new ContainerTask(tx, ContainerTaskType.DELETE,
95  	// (ContainerRef) notifContainer),
96  	// new ContainerTask(tx, ContainerTaskType.DELETE, notifContainer),
97  	// new ShutdownTask(),
98  	// new TransactionTask(),
99  	// new TransactionTask(TransactionTaskType.COMMIT, tx),
100 	// new TransactionTask(TransactionTaskType.ROLLBACK, tx),
101 	// new OperationTask(OperationTaskType.READ,
102 	// new ArrayList<Entry>(), notifContainer, tx,
103 	// new ArrayList<Selector>(), 1934),
104 	// new OperationTask(OperationTaskType.READ,
105 	// new ArrayList<Entry>(), notifContainer, tx,
106 	// java.util.Arrays.asList(selectors), 1934),
107 	// new OperationTask(OperationTaskType.DESTROY,
108 	// new ArrayList<Entry>(), notifContainer, tx,
109 	// java.util.Arrays.asList(selectors), 1934),
110 	// new OperationTask(OperationTaskType.WRITE, java.util.Arrays
111 	// .asList(entries), notifContainer, tx, null, 1934),
112 	// new OperationTask(OperationTaskType.WRITE,
113 	// java.util.Arrays
114 	// .asList(new Entry[] { (new ExceptionEntry(
115 	// "DogTiredException",
116 	// "I need to go to bed.")) }),
117 	// notifContainer, tx, null, 1934) };
118 	//
119 	// XMLOutputFactory factory = XMLOutputFactory.newInstance();
120 	// XMLStreamWriter writer;
121 	// XMLMarshaller xmlwriter = new XMLMarshaller();
122 	//
123 	// int i = 0;
124 	// for (Task t : tasks) {
125 	// i++;
126 	// t.setAnswerToContainer(new URI("tcpjava://localhost:4321/lala"));
127 	// OutputStream out = new ByteArrayOutputStream();
128 	// writer = factory.createXMLStreamWriter(out);
129 	// xmlwriter.writeXMLStartElements(writer, t.getAnswerToContainer()
130 	// .toString());
131 	// if (t instanceof ClearTask) {
132 	// xmlwriter.write((ClearTask) t, writer);
133 	// } else if (t instanceof AspectTask) {
134 	// xmlwriter.write((AspectTask) t, writer);
135 	// } else if (t instanceof ContainerTask) {
136 	// xmlwriter.write((ContainerTask) t, writer);
137 	// } else if (t instanceof ShutdownTask) {
138 	// xmlwriter.write((ShutdownTask) t, writer);
139 	// } else if (t instanceof TransactionTask) {
140 	// xmlwriter.write((TransactionTask) t, writer);
141 	// } else if (t instanceof OperationTask) {
142 	// xmlwriter.write((OperationTask) t, writer);
143 	// }
144 	// xmlwriter.writeXMLEndElements(writer);
145 	//
146 	// if (out instanceof ByteArrayOutputStream) {
147 	// Task task = xmlwriter.read(((ByteArrayOutputStream) out)
148 	// .toByteArray());
149 	// System.out.println(out.toString());
150 	// }
151 	//
152 	// }
153 	//
154 	// }
155 
156 	public byte[] marshall(Task t) {
157 		try {
158 			XMLOutputFactory factory = XMLOutputFactory.newInstance();
159 			XMLStreamWriter writer;
160 			OutputStream out = new ByteArrayOutputStream();
161 			writer = factory.createXMLStreamWriter(out);
162 			String answerToContainer = null;
163 			if (t.getAnswerToContainer() != null) {
164 				answerToContainer = t.getAnswerToContainer().toString();
165 			}
166 			this.writeXMLStartElements(writer, answerToContainer);
167 			if (t instanceof ClearTask) {
168 				this.write((ClearTask) t, writer);
169 			} else if (t instanceof AspectTask) {
170 				this.write((AspectTask) t, writer);
171 			} else if (t instanceof ContainerTask) {
172 				this.write((ContainerTask) t, writer);
173 			} else if (t instanceof ShutdownTask) {
174 				this.write((ShutdownTask) t, writer);
175 			} else if (t instanceof TransactionTask) {
176 				this.write((TransactionTask) t, writer);
177 			} else if (t instanceof OperationTask) {
178 				this.write((OperationTask) t, writer);
179 			}
180 			this.writeXMLEndElements(writer);
181 
182 			if (logger.isDebugEnabled()) {
183 				logger.debug("<< "
184 						+ new String(((ByteArrayOutputStream) out)
185 								.toByteArray()));
186 			}
187 			System.err.println(new String(((ByteArrayOutputStream) out)
188 					.toByteArray()));
189 			return ((ByteArrayOutputStream) out).toByteArray();
190 		} catch (Exception e) {
191 			throw new FatalException(e);
192 		}
193 	}
194 
195 	public Task unmarshall(byte[] x) {
196 		try {
197 			if (logger.isDebugEnabled()) {
198 				logger.debug(">> " + new String(x));
199 			}
200 			String xx = new String(x);
201 			xx = xx.replaceAll(">//W*<", "><");
202 			xx = xx.replaceAll("\r\n", "");
203 			xx = xx.replaceAll("\n", "");
204 			x = xx.getBytes();
205 
206 			System.out.println(new String(x));
207 			Task t = this.read(x);
208 			if (logger.isDebugEnabled()) {
209 				logger.debug("Unmarshalled task: " + t);
210 			}
211 			return t;
212 		} catch (Exception e) {
213 			throw new FatalException(e);
214 		}
215 	}
216 
217 	private void writeXMLStartElements(XMLStreamWriter writer,
218 			String answerToContainer) throws XMLStreamException {
219 		writer.writeStartDocument();
220 		writer.writeStartElement("capi");
221 		writer.writeDefaultNamespace(NAMESPACEURI);
222 		if (answerToContainer != null) {
223 			writer.writeAttribute("answerToContainer", answerToContainer);
224 		}
225 	}
226 
227 	private void writeXMLEndElements(XMLStreamWriter writer)
228 			throws XMLStreamException {
229 		writer.writeEndElement();
230 		writer.writeEndDocument();
231 		writer.writeCharacters("\n");
232 		writer.close();
233 	}
234 
235 	private void write(ClearTask t, XMLStreamWriter writer)
236 			throws XMLStreamException {
237 		writer.writeEmptyElement("clearSpace");
238 	}
239 
240 	private void write(AspectTask t, XMLStreamWriter writer)
241 			throws XMLStreamException {
242 		switch (t.getType()) {
243 		case ADD:
244 			writer.writeStartElement("addAspect");
245 			// TODO implement support for other aspect types (.net, python,
246 			// scheme)
247 			if (t.getAspect() instanceof NotificationAspect) {
248 				writer.writeAttribute("type", "interop");
249 				if (t.getCref() != null) {
250 					writer.writeAttribute("containerReference", t.getCref()
251 							.asURI().toASCIIString());
252 				}
253 				writer.writeStartElement("value");
254 				writer.writeCharacters("NotificationAspect");
255 				writer.writeEndElement();
256 			} else {
257 
258 				writer.writeAttribute("type", "java");
259 				if (t.getCref() != null) {
260 					writer.writeAttribute("containerReference", t.getCref()
261 							.asURI().toASCIIString());
262 				}
263 				writer.writeStartElement("value");
264 				writer.writeCharacters(t.getAspect().getClass().getName());
265 				writer.writeEndElement();
266 			}
267 			writer.writeStartElement("ipoints");
268 			for (IPoint p : t.getPoints()) {
269 				writer.writeStartElement("ipoint");
270 				writer.writeCharacters(p.toString());
271 				writer.writeEndElement();
272 			}
273 			writer.writeEndElement();
274 			this.writeProperties(t.getAspect().getProperties(), writer);
275 			// TODO implement aspect properties.
276 			writer.writeEndElement();
277 			break;
278 		case DELETE:
279 			writer.writeStartElement("removeAspect");
280 			writer.writeAttribute("uri", t.getAspectURI().toASCIIString());
281 			if (t.getCref() != null) {
282 				writer.writeAttribute("containerReference", t.getCref().asURI()
283 						.toASCIIString());
284 			}
285 			writer.writeStartElement("ipoints");
286 			for (IPoint p : t.getPoints()) {
287 				writer.writeStartElement("ipoint");
288 				writer.writeCharacters(p.toString());
289 				writer.writeEndElement();
290 			}
291 			writer.writeEndElement();
292 			writer.writeEndElement();
293 			break;
294 		default:
295 			throw new IllegalArgumentException("AspectTask Type not set!");
296 		}
297 	}
298 
299 	private void write(ContainerTask t, XMLStreamWriter writer)
300 			throws XMLStreamException {
301 		switch (t.getType()) {
302 		case CREATE:
303 			writer.writeStartElement("createContainer");
304 			this.writeContainerCommons(t, writer);
305 			writer.writeAttribute("size", "" + t.getSize());
306 			if (t.getCoordinators().length > 0) {
307 				writer.writeStartElement("coordinators");
308 				for (ICoordinator c : t.getCoordinators()) {
309 					writer.writeStartElement("coordinator");
310 					writer
311 							.writeAttribute("class", c.getClass()
312 									.getSimpleName());
313 					if (c.getProperties().size() != 0) {
314 						this.writeProperties(c.getProperties(), writer);
315 					}
316 					writer.writeEndElement();
317 				}
318 				writer.writeEndElement();
319 			}
320 			writer.writeEndElement();
321 			break;
322 		case DELETE:
323 			writer.writeStartElement("deleteContainer");
324 			this.writeContainerCommons(t, writer);
325 			if (t.getCref() != null) {
326 				writer.writeAttribute("containerReference", t.getCref().asURI()
327 						.toASCIIString());
328 			}
329 			writer.writeEndElement();
330 			break;
331 		}
332 	}
333 
334 	private void writeContainerCommons(ContainerTask t, XMLStreamWriter writer)
335 			throws XMLStreamException {
336 		if (t.getTx() != null) {
337 			writer.writeAttribute("transaction", t.getTx().asURI()
338 					.toASCIIString());
339 		}
340 	}
341 
342 	private void write(ShutdownTask t, XMLStreamWriter writer)
343 			throws XMLStreamException {
344 		writer.writeEmptyElement("shutdown");
345 	}
346 
347 	private void write(TransactionTask t, XMLStreamWriter writer)
348 			throws XMLStreamException {
349 		switch (t.getType()) {
350 		case CREATE:
351 			writer.writeEmptyElement("createTransaction");
352 			writer.writeAttribute("timeout", "" + t.getTimeout());
353 			break;
354 		case COMMIT:
355 			writer.writeEmptyElement("commitTransaction");
356 			writer.writeAttribute("transaction", t.getTx().asURI()
357 					.toASCIIString());
358 			break;
359 		case ROLLBACK:
360 			writer.writeEmptyElement("rollbackTransaction");
361 			writer.writeAttribute("transaction", t.getTx().asURI()
362 					.toASCIIString());
363 			break;
364 		}
365 	}
366 
367 	private void write(OperationTask t, XMLStreamWriter writer)
368 			throws XMLStreamException {
369 		switch (t.getType()) {
370 		case READ:
371 			writer.writeStartElement("read");
372 			this.writeReadCommons(t, writer);
373 			writer.writeEndElement();
374 			break;
375 		case WRITE:
376 			writer.writeStartElement("write");
377 			this.writeWriteCommons(t, writer);
378 			writer.writeStartElement("entries");
379 			this.writeEntries(t.getEntries(), writer, -1);
380 			writer.writeEndElement();
381 			writer.writeEndElement();
382 			break;
383 		case TAKE:
384 			writer.writeStartElement("take");
385 			this.writeReadCommons(t, writer);
386 			writer.writeEndElement();
387 			break;
388 		case SHIFT:
389 			writer.writeStartElement("shift");
390 			this.writeWriteCommons(t, writer);
391 			writer.writeStartElement("entries");
392 			this.writeEntries(t.getEntries(), writer, -1);
393 			writer.writeEndElement();
394 			writer.writeEndElement();
395 			break;
396 		case DESTROY:
397 			writer.writeStartElement("destroy");
398 			this.writeReadCommons(t, writer);
399 			writer.writeEndElement();
400 			break;
401 		default:
402 			throw new FatalException(t.getType() + " is not supported");
403 		}
404 	}
405 
406 	private void writeWriteCommons(OperationTask t, XMLStreamWriter writer)
407 			throws XMLStreamException {
408 		writer.writeAttribute("containerReference", t.getCref().asURI()
409 				.toASCIIString());
410 		if (t.getTx() != null) {
411 			writer.writeAttribute("transaction", t.getTx().asURI()
412 					.toASCIIString());
413 		}
414 		writer.writeAttribute("timeout", "" + t.getTimeout());
415 	}
416 
417 	private void writeReadCommons(OperationTask t, XMLStreamWriter writer)
418 			throws XMLStreamException {
419 		writer.writeAttribute("containerReference", t.getCref().asURI()
420 				.toASCIIString());
421 		if (t.getTx() != null) {
422 			writer.writeAttribute("transaction", t.getTx().asURI()
423 					.toASCIIString());
424 		}
425 		writer.writeAttribute("timeout", "" + t.getTimeout());
426 
427 		this.writeSelectors(t.getSelectors(), writer);
428 	}
429 
430 	private void writeSelectors(List<Selector> selectors, XMLStreamWriter writer)
431 			throws XMLStreamException {
432 		if (selectors != null && selectors.size() > 0) {
433 			writer.writeStartElement("selectors");
434 			for (Selector s : selectors) {
435 				if (s != null) {
436 					writer.writeStartElement("selector");
437 					writer
438 							.writeAttribute("class", s.getClass()
439 									.getSimpleName());
440 					writer.writeAttribute("count", "" + s.getCount());
441 					Properties props = s.getProperties();
442 					this.writeProperties(props, writer);
443 					writer.writeEndElement();
444 				}
445 			}
446 			writer.writeEndElement();
447 		}
448 	}
449 
450 	private void writeProperties(Properties props, XMLStreamWriter writer)
451 			throws XMLStreamException {
452 		if (props != null && props.size() != 0) {
453 			writer.writeStartElement("properties");
454 			for (Object o : props.keySet()) {
455 				writer.writeStartElement("property");
456 				writer.writeAttribute("key", o.toString());
457 				Object value = props.get(o);
458 				if (value instanceof Entry) {
459 					this.writeEntries(java.util.Arrays.asList((Entry) value),
460 							writer, -1);
461 				} else {
462 					// write as String;
463 					writer.writeCharacters(value.toString());
464 					// this.writeEntries(java.util.Arrays
465 					// .asList((Entry) new AtomicEntry<String>(value
466 					// .toString())), writer, -1);
467 				}
468 				writer.writeEndElement();
469 			}
470 			writer.writeEndElement();
471 		}
472 	}
473 
474 	private void writeEntries(List<Entry> entries, XMLStreamWriter writer,
475 			int position) throws XMLStreamException {
476 
477 		if (entries.size() == 0) {
478 			entries.add(new VoidEntry());
479 		}
480 
481 		for (Entry t : entries) {
482 			if (t == null) {
483 				// skip null entries (can happen if a tuple is used as template)
484 				continue;
485 			}
486 			switch (t.getEntryType()) {
487 			case TUPLE:
488 				writer.writeStartElement("entry");
489 				writer.writeAttribute("type", "tuple");
490 				if (position >= 0) {
491 					writer.writeAttribute("position", "" + position);
492 				}
493 				writer.writeAttribute("size", "" + ((Tuple) t).size());
494 				this.writeSelectors(t.getSelectors(), writer);
495 				int i = 0;
496 				writer.writeStartElement("value");
497 				for (Entry e : ((Tuple) t).toArray()) {
498 					this.writeEntries(java.util.Arrays.asList(e), writer, i++);
499 				}
500 				writer.writeEndElement();
501 				writer.writeEndElement();
502 				break;
503 			case ATOMICENTRY:
504 				Class<?> valueClass = ((AtomicEntry<?>) t).getValueClass();
505 				if (!(valueClass.equals(Boolean.class)
506 						|| valueClass.equals(Character.class)
507 						|| valueClass.equals(Byte.class)
508 						|| valueClass.equals(Short.class)
509 						|| valueClass.equals(Integer.class)
510 						|| valueClass.equals(Long.class)
511 						|| valueClass.equals(Float.class)
512 						|| valueClass.equals(Double.class)
513 						|| valueClass.equals(String.class) || valueClass
514 						.equals(URI.class))) {
515 					throw new FatalException(
516 							"Only primitive types (+ String and URI) can be used with XML. "
517 									+ valueClass + " not allowed.");
518 				}
519 
520 				writer.writeStartElement("entry");
521 				writer.writeAttribute("type", valueClass.getSimpleName()
522 						.toLowerCase());
523 				if (position >= 0) {
524 					writer.writeAttribute("position", "" + position);
525 				}
526 				if (((AtomicEntry<?>) t).getValue() != null) {
527 					writer.writeStartElement("value");
528 					writer
529 							.writeCharacters(""
530 									+ ((AtomicEntry<?>) t).getValue());
531 					writer.writeEndElement();
532 				}
533 				this.writeSelectors(t.getSelectors(), writer);
534 				writer.writeEndElement();
535 				break;
536 			case VOID:
537 				writer.writeEmptyElement("voidEntry");
538 				break;
539 			case EXCEPTION:
540 				writer.writeEmptyElement("exceptionEntry");
541 				String exceptionName = ((ExceptionEntry) t).getName();
542 				if (exceptionName.equals("ContainerFullException")) {
543 					exceptionName = "XvsmOperationFailedException";
544 				} else if (exceptionName.equals("CountNotMetException")) {
545 					exceptionName = "XvsmOperationFailedException";
546 				} else if (exceptionName.equals("FatalException")) {
547 					exceptionName = "XvsmFatalCoreException";
548 				} else if (exceptionName.equals("InvalidContainerException")) {
549 					exceptionName = "XvsmContainerNotFoundException";
550 				} else if (exceptionName.equals("InvalidTransactionException")) {
551 					exceptionName = "XvsmTransactionNotFoundException";
552 				} else if (exceptionName
553 						.equals("NoSuchCoordinationTypeException")) {
554 					exceptionName = "XvsmContainerReadException";
555 				} else if (exceptionName.equals("TimeoutExpiredException")) {
556 					exceptionName = "XvsmOperationTimeoutException";
557 				}
558 
559 				writer.writeAttribute("name", exceptionName);
560 				String descr = ((ExceptionEntry) t).getDesription();
561 				writer.writeAttribute("Description",
562 						descr == null ? ((ExceptionEntry) t).getName()
563 								: ((ExceptionEntry) t).getName() + " " + descr);
564 				break;
565 			}
566 		}
567 	}
568 
569 	public Task read(byte[] xml) throws XMLStreamException, URISyntaxException,
570 			ClassNotFoundException {
571 		XMLInputFactory factory = XMLInputFactory.newInstance();
572 		XMLStreamReader parser = factory
573 				.createXMLStreamReader(new ByteArrayInputStream(xml));
574 		Task task = null;
575 
576 		URI answerToContainer = null;
577 
578 		while (parser.hasNext()) {
579 			int event = parser.next();
580 			switch (event) {
581 			case XMLStreamConstants.END_DOCUMENT:
582 				parser.close();
583 				break;
584 			case XMLStreamConstants.START_ELEMENT:
585 				String element = parser.getLocalName();
586 				if (element.equals("capi")) {
587 					answerToContainer = this.readAnswerToContainer(parser);
588 				} else if (element.equals("clearSpace")) {
589 					task = this.readClearSpace(parser);
590 				} else if (element.equals("addAspect")) {
591 					task = this.readAddAspect(parser);
592 				} else if (element.equals("removeAspect")) {
593 					task = this.readRemoveAspect(parser);
594 				} else if (element.equals("createContainer")) {
595 					task = this.readCreateContainer(parser);
596 				} else if (element.equals("deleteContainer")) {
597 					task = this.readDeleteContainer(parser);
598 				} else if (element.equals("getContainer")) {
599 					task = this.readGetContainer(parser);
600 				} else if (element.equals("shutdown")) {
601 					task = this.readShutdown(parser);
602 				} else if (element.equals("createTransaction")) {
603 					task = this.readCreateTransaction(parser);
604 				} else if (element.equals("commitTransaction")) {
605 					task = this.readTransaction(parser);
606 					((TransactionTask) task)
607 							.setType(TransactionTaskType.COMMIT);
608 				} else if (element.equals("rollbackTransaction")) {
609 					task = this.readTransaction(parser);
610 					((TransactionTask) task)
611 							.setType(TransactionTaskType.ROLLBACK);
612 				} else if (element.equals("read")) {
613 					task = this.readRead(parser);
614 				} else if (element.equals("write")) {
615 					task = this.readWrite(parser);
616 				} else if (element.equals("take")) {
617 					task = this.readTake(parser);
618 				} else if (element.equals("shift")) {
619 					task = this.readShift(parser);
620 				} else if (element.equals("destroy")) {
621 					task = this.readDestroy(parser);
622 				} else {
623 					throw new FatalException("UNKNOWN ELEMENT: " + element);
624 				}
625 				break;
626 			default:
627 				break;
628 			}
629 		}
630 		task.setAnswerToContainer(answerToContainer);
631 		return task;
632 	}
633 
634 	private URI readAnswerToContainer(XMLStreamReader parser)
635 			throws URISyntaxException {
636 		URI answerToContainer = null;
637 		for (int i = 0; i < parser.getAttributeCount(); i++) {
638 			String attribute = parser.getAttributeLocalName(i);
639 			if (attribute.equals("answerToContainer")) {
640 				answerToContainer = new URI(parser.getAttributeValue(i));
641 			} else {
642 				// TODO
643 			}
644 
645 		}
646 		return answerToContainer;
647 	}
648 
649 	private ClearTask readClearSpace(XMLStreamReader parser)
650 			throws URISyntaxException {
651 		ClearTask task = new ClearTask();
652 		return task;
653 	}
654 
655 	private AspectTask readAddAspect(XMLStreamReader parser)
656 			throws URISyntaxException, XMLStreamException,
657 			ClassNotFoundException {
658 		String aspectType = null;
659 		String aspect = null;
660 		AspectTask task = null;
661 		List<IPoint> ipoints = new ArrayList<IPoint>();
662 		Properties props = null;
663 		ContainerRef cref = null;
664 
665 		for (int i = 0; i < parser.getAttributeCount(); i++) {
666 			String attribute = parser.getAttributeLocalName(i);
667 			if (attribute.equals("type")) {
668 				aspectType = parser.getAttributeValue(i);
669 			}
670 			if (attribute.equals("containerReference")) {
671 				cref = new ContainerRef(new URI(parser.getAttributeValue(i)));
672 			}
673 		}
674 
675 		try {
676 			while (parser.hasNext()) {
677 				int event = parser.next();
678 				switch (event) {
679 				case XMLStreamConstants.START_ELEMENT:
680 					String element = parser.getLocalName();
681 					if (element.equals("value")) {
682 						aspect = parser.getElementText();
683 					} else if (element.equals("ipoints")) {
684 						continue;
685 					} else if (element.equals("ipoint")) {
686 						String txt = parser.getElementText();
687 						try {
688 							ipoints.add(LocalIPoint.valueOf(txt));
689 						} catch (IllegalArgumentException e) {
690 							ipoints.add(GlobalIPoint.valueOf(txt));
691 						}
692 					} else if (element.equals("properties")) {
693 						props = this.readProperties(parser);
694 					}
695 					break;
696 				case XMLStreamConstants.END_ELEMENT:
697 					element = parser.getLocalName();
698 					if (element.equals("addAspect")) {
699 						IAspect iaspect = null;
700 						if (aspectType.equals("java")) {
701 							iaspect = (IAspect) Class.forName(aspect)
702 									.newInstance();
703 						} else if (aspectType.equals("interop")) {
704 							if (aspect.equals("NotificationAspect")) {
705 								iaspect = new NotificationAspect();
706 							}
707 						} else {
708 							throw new FatalException(aspectType
709 									+ " aspects are not supported");
710 						}
711 						iaspect.setProperties(props);
712 						task = new AspectTask(AspectTaskType.ADD, cref,
713 								iaspect, ipoints);
714 					}
715 				}
716 			}
717 		} catch (InstantiationException e) {
718 			throw new FatalException(e);
719 		} catch (IllegalAccessException e) {
720 			throw new FatalException(e);
721 		}
722 		return task;
723 	}
724 
725 	private AspectTask readRemoveAspect(XMLStreamReader parser)
726 			throws URISyntaxException {
727 		List<IPoint> ipoints = new ArrayList<IPoint>();
728 		Properties props = null;
729 		URI uri = null;
730 		URI answerToContainer = null;
731 		ContainerRef cref = null;
732 		for (int i = 0; i < parser.getAttributeCount(); i++) {
733 			String attribute = parser.getAttributeLocalName(i);
734 			if (attribute.equals("uri")) {
735 				uri = new URI(parser.getAttributeValue(i));
736 			} else if (attribute.equals("answerToContainer")) {
737 				answerToContainer = new URI(parser.getAttributeValue(i));
738 			} else if (attribute.equals("containerReference")) {
739 				cref = new ContainerRef(new URI(parser.getAttributeValue(i)));
740 			}
741 		}
742 
743 		try {
744 			while (parser.hasNext()) {
745 				int event = parser.next();
746 				switch (event) {
747 				case XMLStreamConstants.START_ELEMENT:
748 					String element = parser.getLocalName();
749 					if (element.equals("ipoints")) {
750 						continue;
751 					} else if (element.equals("ipoint")) {
752 						String txt = parser.getElementText();
753 						try {
754 							ipoints.add(LocalIPoint.valueOf(txt));
755 						} catch (IllegalArgumentException e) {
756 							ipoints.add(GlobalIPoint.valueOf(txt));
757 						}
758 					} else if (element.equals("properties")) {
759 						props = this.readProperties(parser);
760 					}
761 				}
762 			}
763 		} catch (Exception e) {
764 			e.printStackTrace();
765 			throw new FatalException(e);
766 		}
767 		AspectTask task = new AspectTask(AspectTaskType.DELETE, cref, uri,
768 				ipoints);
769 		task.setAnswerToContainer(answerToContainer);
770 		task.setAspectContext(props);
771 
772 		return task;
773 	}
774 
775 	private ContainerTask readCreateContainer(XMLStreamReader parser)
776 			throws XMLStreamException, URISyntaxException,
777 			ClassNotFoundException {
778 		ContainerTask task = new ContainerTask(ContainerTaskType.CREATE);
779 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
780 
781 		List<ICoordinator> coordinators = new ArrayList<ICoordinator>();
782 
783 		for (int i = 0; i < parser.getAttributeCount(); i++) {
784 			String attribute = parser.getAttributeLocalName(i);
785 			if (attribute.equals("transaction")) {
786 				task
787 						.setTx(new Transaction(new URI(parser
788 								.getAttributeValue(i))));
789 			} else if (attribute.equals("size")) {
790 				task.setSize(Integer.parseInt(parser.getAttributeValue(i)));
791 			} else {
792 				// TODO
793 			}
794 		}
795 		while (parser.hasNext()) {
796 			int event = parser.next();
797 			switch (event) {
798 			case XMLStreamConstants.START_ELEMENT:
799 				String element = parser.getLocalName();
800 				if (element.equals("coordinators")) {
801 					continue;
802 				} else if (element.equals("coordinator")) {
803 					for (int i = 0; i < parser.getAttributeCount(); i++) {
804 						String attribute = parser.getAttributeLocalName(i);
805 						if (attribute.equals("class")) {
806 							Class<?> c = Class.forName("org.xvsm.coordinators."
807 									+ parser.getAttributeValue(i));
808 							try {
809 								coordinators
810 										.add((ICoordinator) c.newInstance());
811 							} catch (Exception e) {
812 								throw new FatalException(e);
813 							}
814 						}
815 					}
816 				} else if (element.equals("properties")) {
817 					coordinators.get(coordinators.size() - 1).setProperties(
818 							this.readProperties(parser));
819 				}
820 				break;
821 			default:
822 				// TODO
823 			}
824 		}
825 		task.setCoordinators(coordinators.toArray(new ICoordinator[0]));
826 		return task;
827 	}
828 
829 	private ContainerTask readDeleteContainer(XMLStreamReader parser)
830 			throws XMLStreamException, URISyntaxException {
831 		ContainerTask task = new ContainerTask(ContainerTaskType.DELETE);
832 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
833 		for (int i = 0; i < parser.getAttributeCount(); i++) {
834 			String attribute = parser.getAttributeLocalName(i);
835 			if (attribute.equals("transaction")) {
836 				task
837 						.setTx(new Transaction(new URI(parser
838 								.getAttributeValue(i))));
839 			} else if (attribute.equals("containerReference")) {
840 				task.setCref(new ContainerRef(new URI(parser
841 						.getAttributeValue(i))));
842 			} else {
843 				// TODO
844 			}
845 		}
846 		return task;
847 	}
848 
849 	private ContainerTask readGetContainer(XMLStreamReader parser)
850 			throws XMLStreamException, URISyntaxException {
851 		ContainerTask task = new ContainerTask(ContainerTaskType.GET);
852 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
853 		for (int i = 0; i < parser.getAttributeCount(); i++) {
854 			String attribute = parser.getAttributeLocalName(i);
855 			if (attribute.equals("transaction")) {
856 				task
857 						.setTx(new Transaction(new URI(parser
858 								.getAttributeValue(i))));
859 			} else {
860 				// TODO
861 			}
862 		}
863 		return task;
864 	}
865 
866 	private ShutdownTask readShutdown(XMLStreamReader parser)
867 			throws XMLStreamException, URISyntaxException {
868 		ShutdownTask task = new ShutdownTask();
869 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
870 		return task;
871 	}
872 
873 	private TransactionTask readCreateTransaction(XMLStreamReader parser)
874 			throws XMLStreamException, URISyntaxException {
875 		TransactionTask task = new TransactionTask();
876 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
877 		for (int i = 0; i < parser.getAttributeCount(); i++) {
878 			String attribute = parser.getAttributeLocalName(i);
879 			if (attribute.equals("timeout")) {
880 				task.setTimeout(Long.parseLong(parser.getAttributeValue(i)));
881 			} else {
882 				// TODO
883 			}
884 		}
885 		return task;
886 	}
887 
888 	private TransactionTask readTransaction(XMLStreamReader parser)
889 			throws XMLStreamException, URISyntaxException {
890 		TransactionTask task = new TransactionTask();
891 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
892 
893 		for (int i = 0; i < parser.getAttributeCount(); i++) {
894 			String attribute = parser.getAttributeLocalName(i);
895 			if (attribute.equals("transaction")) {
896 				task
897 						.setTx(new Transaction(new URI(parser
898 								.getAttributeValue(i))));
899 
900 			}
901 		}
902 		return task;
903 	}
904 
905 	private OperationTask readOperationTaskCommons(OperationTask task,
906 			XMLStreamReader parser) throws XMLStreamException,
907 			URISyntaxException, ClassNotFoundException {
908 		// task.setAnswerToContainer(this.readAnswerToContainer(parser));
909 		List<Entry> entries = new ArrayList<Entry>();
910 
911 		for (int i = 0; i < parser.getAttributeCount(); i++) {
912 			String attribute = parser.getAttributeLocalName(i);
913 			if (attribute.equals("containerReference")) {
914 				task.setCref(new ContainerRef(new URI(parser
915 						.getAttributeValue(i))));
916 			} else if (attribute.equals("transaction")) {
917 				task
918 						.setTx(new Transaction(new URI(parser
919 								.getAttributeValue(i))));
920 			} else if (attribute.equals("timeout")) {
921 				task.setTimeout(Long.parseLong(parser.getAttributeValue(i)));
922 			} else {
923 				// TODO
924 			}
925 		}
926 		while (parser.hasNext()) {
927 			int event = parser.next();
928 			switch (event) {
929 			case XMLStreamConstants.START_ELEMENT:
930 				String element = parser.getLocalName();
931 				if (element.equals("selectors")) {
932 					task.setSelectors(this.readSelectors(parser));
933 				} else if (element.equals("entries")) {
934 					continue;
935 				} else if (element.equals("entry")) {
936 					entries.add(this.readEntry(parser, null));
937 				} else if (element.equals("voidEntry")) {
938 					entries.add(new VoidEntry());
939 				} else if (element.equals("exceptionEntry")) {
940 					ExceptionEntry e = new ExceptionEntry();
941 					for (int i = 0; i < parser.getAttributeCount(); i++) {
942 						String attribute = parser.getAttributeLocalName(i);
943 						if (attribute.equals("name")) {
944 							String name = parser.getAttributeValue(i);
945 							if (name.equals("XvsmOperationFailedException")) {
946 								name = "CountNotMetException";
947 							} else if (name.equals("XvsmFatalCoreException")) {
948 								name = "FatalException";
949 							} else if (name
950 									.equals("XvsmContainerNotFoundException")) {
951 								name = "InvalidContainerException";
952 							} else if (name
953 									.equals("XvsmTransactionNotFoundException")) {
954 								name = "InvalidTransactionException";
955 							} else if (name
956 									.equals("XvsmContainerReadException")) {
957 								name = "NoSuchCoordinationTypeException";
958 							} else if (name
959 									.equals("XvsmOperationTimeoutException")) {
960 								name = "TimeoutExpiredException";
961 							}
962 							e.setName(name);
963 						} else if (attribute.equals("description")) {
964 							e.setDesription(parser.getAttributeValue(i));
965 						} else {
966 							// TODO
967 						}
968 					}
969 					entries.add(e);
970 				}
971 				break;
972 			default:
973 				// TODO
974 			}
975 		}
976 		task.setEntries(entries);
977 		return task;
978 	}
979 
980 	private Entry readTuple(XMLStreamReader parser, int size)
981 			throws ClassNotFoundException, XMLStreamException {
982 		Tuple tuple = new Tuple(size);
983 		while (parser.hasNext()) {
984 			int event = parser.next();
985 			switch (event) {
986 			case XMLStreamConstants.START_ELEMENT:
987 				String element = parser.getLocalName();
988 				if (element.equals("value")) {
989 					continue;
990 				} else if (element.equals("entry")) {
991 					// tuple.add(this.readEntry(parser));
992 					this.readEntry(parser, tuple);
993 				} else if (element.equals("selectors")) {
994 					tuple.setSelectors(this.readSelectors(parser));
995 				}
996 				break;
997 			case XMLStreamConstants.END_ELEMENT:
998 				if (parser.getLocalName().equals("entry")) {
999 					return tuple;
1000 				}
1001 				break;
1002 			}
1003 		}
1004 		return tuple;
1005 	}
1006 
1007 	/***
1008 	 * 
1009 	 * @param parser
1010 	 * @param tuple
1011 	 *            a tuple to which the entry shall be added.
1012 	 * @return
1013 	 * @throws ClassNotFoundException
1014 	 * @throws XMLStreamException
1015 	 */
1016 	private Entry readEntry(XMLStreamReader parser, Tuple tuple)
1017 			throws ClassNotFoundException, XMLStreamException {
1018 		Object o = null;
1019 		int position = -1;
1020 		int size = -1;
1021 		Class c = null;
1022 		List<Selector> selectors = null;
1023 		String type = null;
1024 
1025 		for (int i = 0; i < parser.getAttributeCount(); i++) {
1026 			String attr = parser.getAttributeLocalName(i);
1027 			if (attr.equals("position")) {
1028 				position = Integer.parseInt(parser.getAttributeValue(i));
1029 			} else if (attr.equals("size")) {
1030 				size = Integer.parseInt(parser.getAttributeValue(i));
1031 			} else if (attr.equals("type")) {
1032 				type = parser.getAttributeValue(i);
1033 				if (type.equals("tuple")) {
1034 				} else if (type.equals("uri")) {
1035 					c = java.net.URI.class;
1036 				} else {
1037 					c = Class.forName("java.lang."
1038 							+ type.substring(0, 1).toUpperCase()
1039 							+ type.substring(1, type.length()));
1040 				}
1041 			}
1042 		}
1043 		while (parser.hasNext()) {
1044 			int event = parser.next();
1045 			switch (event) {
1046 			case XMLStreamConstants.START_ELEMENT:
1047 				String element = parser.getLocalName();
1048 				if (element.equals("value")) {
1049 					if (type.equals("tuple")) {
1050 						Entry e = this.readTuple(parser, size);
1051 						if (tuple != null) {
1052 							tuple.setEntry(position, e);
1053 						}
1054 						if (selectors != null) {
1055 							e.setSelectors(selectors);
1056 							// selectors = null;
1057 						}
1058 						return e;
1059 					} else {
1060 						String value = parser.getElementText();
1061 						if (c.equals(Integer.class)) {
1062 							o = Integer.parseInt(value);
1063 						} else if (c.equals(Boolean.class)) {
1064 							o = Boolean.parseBoolean(value);
1065 						} else if (c.equals(Character.class)) {
1066 							// TODO check if string is long enough
1067 							o = new Character(value.charAt(0));
1068 						} else if (c.equals(Byte.class)) {
1069 							o = Byte.parseByte(value);
1070 						} else if (c.equals(Short.class)) {
1071 							o = Short.parseShort(value);
1072 						} else if (c.equals(Long.class)) {
1073 							o = Long.parseLong(value);
1074 						} else if (c.equals(Float.class)) {
1075 							o = Float.parseFloat(value);
1076 						} else if (c.equals(Double.class)) {
1077 							o = Double.parseDouble(value);
1078 						} else if (c.equals(String.class)) {
1079 							o = value;
1080 						} else if (c.equals(URI.class)) {
1081 							try {
1082 								o = new java.net.URI(value);
1083 							} catch (URISyntaxException e) {
1084 								throw new FatalException(value
1085 										+ " is not a valid URI");
1086 							}
1087 						} else {
1088 							throw new FatalException(c
1089 									+ " is not a valid type.");
1090 							// TODO
1091 						}
1092 					}
1093 				} else if (element.equals("selectors")) {
1094 					selectors = this.readSelectors(parser);
1095 				}
1096 				break;
1097 			case XMLStreamConstants.END_ELEMENT:
1098 				if (parser.getLocalName().equals("entry")) {
1099 					AtomicEntry<?> e = (o == null) ? (new AtomicEntry<Object>(c))
1100 							: (new AtomicEntry<Object>(o, c));
1101 					if (selectors != null) {
1102 						e.setSelectors(selectors);
1103 					}
1104 					if (tuple != null) {
1105 						tuple.setEntry(position, e);
1106 					}
1107 					return e;
1108 				}
1109 				break;
1110 			}
1111 		}
1112 		return null;
1113 	}
1114 
1115 	private List<Selector> readSelectors(XMLStreamReader parser)
1116 			throws XMLStreamException, ClassNotFoundException {
1117 		List<Selector> selectors = new ArrayList<Selector>();
1118 		Selector s = null;
1119 		while (parser.hasNext()) {
1120 			int event = parser.next();
1121 			switch (event) {
1122 			case XMLStreamConstants.START_ELEMENT:
1123 				String element = parser.getLocalName();
1124 				if (element.equals("selector")) {
1125 					for (int i = 0; i < parser.getAttributeCount(); i++) {
1126 						String attribute = parser.getAttributeLocalName(i);
1127 						if (attribute.equals("class")) {
1128 							Class<?> c;
1129 							Object o;
1130 							try {
1131 								c = Class.forName("org.xvsm.selectors."
1132 										+ parser.getAttributeValue(i));
1133 								Constructor<?> constr = c
1134 										.getConstructor(new Class[0]);
1135 								o = constr.newInstance(new Object[0]);
1136 							} catch (Exception e1) {
1137 								throw new FatalException(e1);
1138 							}
1139 
1140 							try {
1141 								s = (Selector) o;
1142 								selectors.add(s);
1143 							} catch (ClassCastException e) {
1144 								throw new FatalException(e);
1145 							}
1146 						} else if (attribute.equals("count")) {
1147 							int count = Integer.parseInt(parser
1148 									.getAttributeValue(i));
1149 							s.setCount(count);
1150 						}
1151 					}
1152 				} else if (element.equals("properties")) {
1153 					s.setProperties(this.readProperties(parser));
1154 				} else {
1155 					// TODO
1156 				}
1157 				break;
1158 			case XMLStreamConstants.END_ELEMENT:
1159 				element = parser.getLocalName();
1160 				if (element.equals("selector")) {
1161 					continue;
1162 				} else if (element.equals("selectors")) {
1163 					return selectors;
1164 				}
1165 				break;
1166 			}
1167 
1168 		}
1169 		return selectors;
1170 	}
1171 
1172 	private Properties readProperties(XMLStreamReader parser)
1173 			throws XMLStreamException, ClassNotFoundException {
1174 		Properties props = new Properties();
1175 
1176 		Object propName = null;
1177 		Object propVal = null;
1178 		while (parser.hasNext()) {
1179 			int event = parser.next();
1180 			switch (event) {
1181 			case XMLStreamConstants.START_ELEMENT:
1182 				String element = parser.getLocalName();
1183 				if (element.equals("property")) {
1184 					for (int i = 0; i < parser.getAttributeCount(); i++) {
1185 						propName = parser.getAttributeValue(i);
1186 					}
1187 				} else if (element.equals("entry")) {
1188 					propVal = this.readEntry(parser, null);
1189 				}
1190 				break;
1191 			case XMLStreamConstants.CHARACTERS:
1192 				// the content is not an entry it has to be a string.
1193 				// core copied from the javadoc of {@link
1194 				// XMLStreamReader#getElementText()}
1195 				StringBuffer buf = new StringBuffer();
1196 				while (event != XMLStreamConstants.END_ELEMENT) {
1197 					if (event == XMLStreamConstants.CHARACTERS
1198 							|| event == XMLStreamConstants.CDATA
1199 							|| event == XMLStreamConstants.SPACE
1200 							|| event == XMLStreamConstants.ENTITY_REFERENCE) {
1201 						buf.append(parser.getText());
1202 					} else if (event == XMLStreamConstants.PROCESSING_INSTRUCTION
1203 							|| event == XMLStreamConstants.COMMENT) {
1204 						// skipping
1205 					}
1206 					event = parser.next();
1207 				}
1208 				propVal = buf.toString();
1209 			case XMLStreamConstants.END_ELEMENT:
1210 				element = parser.getLocalName();
1211 				if (element.equals("properties")) {
1212 					return props;
1213 				} else if (element.equals("property")) {
1214 					props.put(propName, propVal);
1215 				}
1216 				break;
1217 			}
1218 		}
1219 		return props;
1220 	}
1221 
1222 	private OperationTask readRead(XMLStreamReader parser)
1223 			throws XMLStreamException, URISyntaxException,
1224 			ClassNotFoundException {
1225 		OperationTask task = new OperationTask(OperationTaskType.READ);
1226 		this.readOperationTaskCommons(task, parser);
1227 		return task;
1228 	}
1229 
1230 	private OperationTask readTake(XMLStreamReader parser)
1231 			throws XMLStreamException, URISyntaxException,
1232 			ClassNotFoundException {
1233 		OperationTask task = new OperationTask(OperationTaskType.TAKE);
1234 		this.readOperationTaskCommons(task, parser);
1235 		return task;
1236 	}
1237 
1238 	private OperationTask readDestroy(XMLStreamReader parser)
1239 			throws XMLStreamException, URISyntaxException,
1240 			ClassNotFoundException {
1241 		OperationTask task = new OperationTask(OperationTaskType.DESTROY);
1242 		this.readOperationTaskCommons(task, parser);
1243 		return task;
1244 	}
1245 
1246 	private OperationTask readWrite(XMLStreamReader parser)
1247 			throws XMLStreamException, URISyntaxException,
1248 			ClassNotFoundException {
1249 		OperationTask task = new OperationTask(OperationTaskType.WRITE);
1250 		this.readOperationTaskCommons(task, parser);
1251 		return task;
1252 	}
1253 
1254 	private OperationTask readShift(XMLStreamReader parser)
1255 			throws XMLStreamException, URISyntaxException,
1256 			ClassNotFoundException {
1257 		OperationTask task = new OperationTask(OperationTaskType.SHIFT);
1258 		this.readOperationTaskCommons(task, parser);
1259 		return task;
1260 	}
1261 
1262 }