+ /**
+ * Parses a Sone from the given input stream and creates a new Sone from the
+ * parsed data.
+ *
+ * @param originalSone
+ * The Sone to update
+ * @param soneInputStream
+ * The input stream to parse the Sone from
+ * @return The parsed Sone
+ */
+ public Sone parseSone(Sone originalSone, InputStream soneInputStream) {
+ /* TODO - impose a size limit? */
+
+ Document document;
+ /* XML parsing is not thread-safe. */
+ synchronized (this) {
+ document = XML.transformToDocument(soneInputStream);
+ }
+ if (document == null) {
+ /* TODO - mark Sone as bad. */
+ logger.log(Level.WARNING, "Could not parse XML for Sone %s!", new Object[] { originalSone });
+ return null;
+ }
+
+ Sone sone = new Sone(originalSone.getId()).setIdentity(originalSone.getIdentity());
+
+ SimpleXML soneXml;
+ try {
+ soneXml = SimpleXML.fromDocument(document);
+ } catch (NullPointerException npe1) {
+ /* for some reason, invalid XML can cause NPEs. */
+ logger.log(Level.WARNING, "XML for Sone " + sone + " can not be parsed!", npe1);
+ return null;
+ }
+
+ Integer protocolVersion = null;
+ String soneProtocolVersion = soneXml.getValue("protocol-version", null);
+ if (soneProtocolVersion != null) {
+ protocolVersion = Numbers.safeParseInteger(soneProtocolVersion);
+ }
+ if (protocolVersion == null) {
+ logger.log(Level.INFO, "No protocol version found, assuming 0.");
+ protocolVersion = 0;
+ }
+
+ if (protocolVersion < 0) {
+ logger.log(Level.WARNING, "Invalid protocol version: " + protocolVersion + "! Not parsing Sone.");
+ return null;
+ }
+
+ /* check for valid versions. */
+ if (protocolVersion > MAX_PROTOCOL_VERSION) {
+ logger.log(Level.WARNING, "Unknown protocol version: " + protocolVersion + "! Not parsing Sone.");
+ return null;
+ }
+
+ String soneTime = soneXml.getValue("time", null);
+ if (soneTime == null) {
+ /* TODO - mark Sone as bad. */
+ logger.log(Level.WARNING, "Downloaded time for Sone %s was null!", new Object[] { sone });
+ return null;
+ }
+ try {
+ sone.setTime(Long.parseLong(soneTime));
+ } catch (NumberFormatException nfe1) {
+ /* TODO - mark Sone as bad. */
+ logger.log(Level.WARNING, "Downloaded Sone %s with invalid time: %s", new Object[] { sone, soneTime });
+ return null;
+ }
+
+ SimpleXML clientXml = soneXml.getNode("client");
+ if (clientXml != null) {
+ String clientName = clientXml.getValue("name", null);
+ String clientVersion = clientXml.getValue("version", null);
+ if ((clientName == null) || (clientVersion == null)) {
+ logger.log(Level.WARNING, "Download Sone %s with client XML but missing name or version!", sone);
+ return null;