1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.fourthline.cling.binding.xml;
17
18 import static org.fourthline.cling.model.XMLUtil.appendNewElement;
19 import static org.fourthline.cling.model.XMLUtil.appendNewElementIfNotNull;
20
21 import java.io.StringReader;
22 import java.net.URI;
23 import java.net.URL;
24 import java.util.logging.Logger;
25
26 import javax.xml.parsers.DocumentBuilder;
27 import javax.xml.parsers.DocumentBuilderFactory;
28
29 import org.fourthline.cling.binding.staging.MutableDevice;
30 import org.fourthline.cling.binding.staging.MutableIcon;
31 import org.fourthline.cling.binding.staging.MutableService;
32 import org.fourthline.cling.binding.xml.Descriptor.Device.ELEMENT;
33 import org.fourthline.cling.model.Namespace;
34 import org.fourthline.cling.model.ValidationException;
35 import org.fourthline.cling.model.XMLUtil;
36 import org.fourthline.cling.model.meta.Device;
37 import org.fourthline.cling.model.meta.DeviceDetails;
38 import org.fourthline.cling.model.meta.Icon;
39 import org.fourthline.cling.model.meta.LocalDevice;
40 import org.fourthline.cling.model.meta.LocalService;
41 import org.fourthline.cling.model.meta.RemoteDevice;
42 import org.fourthline.cling.model.meta.RemoteService;
43 import org.fourthline.cling.model.meta.Service;
44 import org.fourthline.cling.model.profile.RemoteClientInfo;
45 import org.fourthline.cling.model.types.DLNACaps;
46 import org.fourthline.cling.model.types.DLNADoc;
47 import org.fourthline.cling.model.types.InvalidValueException;
48 import org.fourthline.cling.model.types.ServiceId;
49 import org.fourthline.cling.model.types.ServiceType;
50 import org.fourthline.cling.model.types.UDN;
51 import org.seamless.util.Exceptions;
52 import org.seamless.util.MimeType;
53 import org.w3c.dom.Document;
54 import org.w3c.dom.Element;
55 import org.w3c.dom.Node;
56 import org.w3c.dom.NodeList;
57 import org.xml.sax.ErrorHandler;
58 import org.xml.sax.InputSource;
59 import org.xml.sax.SAXException;
60 import org.xml.sax.SAXParseException;
61
62
63
64
65
66
67 public class UDA10DeviceDescriptorBinderImpl implements DeviceDescriptorBinder, ErrorHandler {
68
69 private static Logger log = Logger.getLogger(DeviceDescriptorBinder.class.getName());
70
71 public <D extends Device> D describe(D undescribedDevice, String descriptorXml) throws DescriptorBindingException, ValidationException {
72
73 if (descriptorXml == null || descriptorXml.length() == 0) {
74 throw new DescriptorBindingException("Null or empty descriptor");
75 }
76
77 try {
78 log.fine("Populating device from XML descriptor: " + undescribedDevice);
79
80
81
82
83
84
85
86
87 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
88 factory.setNamespaceAware(true);
89 DocumentBuilder documentBuilder = factory.newDocumentBuilder();
90 documentBuilder.setErrorHandler(this);
91
92 Document d = documentBuilder.parse(
93 new InputSource(
94
95 new StringReader(descriptorXml.trim())
96 )
97 );
98
99 return describe(undescribedDevice, d);
100
101 } catch (ValidationException ex) {
102 throw ex;
103 } catch (Exception ex) {
104 throw new DescriptorBindingException("Could not parse device descriptor: " + ex.toString(), ex);
105 }
106 }
107
108 public <D extends Device> D describe(D undescribedDevice, Document dom) throws DescriptorBindingException, ValidationException {
109 try {
110 log.fine("Populating device from DOM: " + undescribedDevice);
111
112
113 MutableDevice descriptor = new MutableDevice();
114 Element rootElement = dom.getDocumentElement();
115 hydrateRoot(descriptor, rootElement);
116
117
118 return buildInstance(undescribedDevice, descriptor);
119
120 } catch (ValidationException ex) {
121 throw ex;
122 } catch (Exception ex) {
123 throw new DescriptorBindingException("Could not parse device DOM: " + ex.toString(), ex);
124 }
125 }
126
127 public <D extends Device> D buildInstance(D undescribedDevice, MutableDevice descriptor) throws ValidationException {
128 return (D) descriptor.build(undescribedDevice);
129 }
130
131 protected void hydrateRoot(MutableDevice descriptor, Element rootElement) throws DescriptorBindingException {
132
133 if (rootElement.getNamespaceURI() == null || !rootElement.getNamespaceURI().equals(Descriptor.Device.NAMESPACE_URI)) {
134 log.warning("Wrong XML namespace declared on root element: " + rootElement.getNamespaceURI());
135 }
136
137 if (!rootElement.getNodeName().equals(ELEMENT.root.name())) {
138 throw new DescriptorBindingException("Root element name is not <root>: " + rootElement.getNodeName());
139 }
140
141 NodeList rootChildren = rootElement.getChildNodes();
142
143 Node deviceNode = null;
144
145 for (int i = 0; i < rootChildren.getLength(); i++) {
146 Node rootChild = rootChildren.item(i);
147
148 if (rootChild.getNodeType() != Node.ELEMENT_NODE)
149 continue;
150
151 if (ELEMENT.specVersion.equals(rootChild)) {
152 hydrateSpecVersion(descriptor, rootChild);
153 } else if (ELEMENT.URLBase.equals(rootChild)) {
154 try {
155 String urlString = XMLUtil.getTextContent(rootChild);
156 if (urlString != null && urlString.length() > 0) {
157
158 descriptor.baseURL = new URL(urlString);
159 }
160 } catch (Exception ex) {
161 throw new DescriptorBindingException("Invalid URLBase: " + ex.getMessage());
162 }
163 } else if (ELEMENT.device.equals(rootChild)) {
164
165 if (deviceNode != null)
166 throw new DescriptorBindingException("Found multiple <device> elements in <root>");
167 deviceNode = rootChild;
168 } else {
169 log.finer("Ignoring unknown element: " + rootChild.getNodeName());
170 }
171 }
172
173 if (deviceNode == null) {
174 throw new DescriptorBindingException("No <device> element in <root>");
175 }
176 hydrateDevice(descriptor, deviceNode);
177 }
178
179 public void hydrateSpecVersion(MutableDevice descriptor, Node specVersionNode) throws DescriptorBindingException {
180
181 NodeList specVersionChildren = specVersionNode.getChildNodes();
182 for (int i = 0; i < specVersionChildren.getLength(); i++) {
183 Node specVersionChild = specVersionChildren.item(i);
184
185 if (specVersionChild.getNodeType() != Node.ELEMENT_NODE)
186 continue;
187
188 if (ELEMENT.major.equals(specVersionChild)) {
189 String version = XMLUtil.getTextContent(specVersionChild).trim();
190 if (!version.equals("1")) {
191 log.warning("Unsupported UDA major version, ignoring: " + version);
192 version = "1";
193 }
194 descriptor.udaVersion.major = Integer.valueOf(version);
195 } else if (ELEMENT.minor.equals(specVersionChild)) {
196 String version = XMLUtil.getTextContent(specVersionChild).trim();
197 if (!version.equals("0")) {
198 log.warning("Unsupported UDA minor version, ignoring: " + version);
199 version = "0";
200 }
201 descriptor.udaVersion.minor = Integer.valueOf(version);
202 }
203
204 }
205
206 }
207
208 public void hydrateDevice(MutableDevice descriptor, Node deviceNode) throws DescriptorBindingException {
209
210 NodeList deviceNodeChildren = deviceNode.getChildNodes();
211 for (int i = 0; i < deviceNodeChildren.getLength(); i++) {
212 Node deviceNodeChild = deviceNodeChildren.item(i);
213
214 if (deviceNodeChild.getNodeType() != Node.ELEMENT_NODE)
215 continue;
216
217 if (ELEMENT.deviceType.equals(deviceNodeChild)) {
218 descriptor.deviceType = XMLUtil.getTextContent(deviceNodeChild);
219 } else if (ELEMENT.friendlyName.equals(deviceNodeChild)) {
220 descriptor.friendlyName = XMLUtil.getTextContent(deviceNodeChild);
221 } else if (ELEMENT.manufacturer.equals(deviceNodeChild)) {
222 descriptor.manufacturer = XMLUtil.getTextContent(deviceNodeChild);
223 } else if (ELEMENT.manufacturerURL.equals(deviceNodeChild)) {
224 descriptor.manufacturerURI = parseURI(XMLUtil.getTextContent(deviceNodeChild));
225 } else if (ELEMENT.modelDescription.equals(deviceNodeChild)) {
226 descriptor.modelDescription = XMLUtil.getTextContent(deviceNodeChild);
227 } else if (ELEMENT.modelName.equals(deviceNodeChild)) {
228 descriptor.modelName = XMLUtil.getTextContent(deviceNodeChild);
229 } else if (ELEMENT.modelNumber.equals(deviceNodeChild)) {
230 descriptor.modelNumber = XMLUtil.getTextContent(deviceNodeChild);
231 } else if (ELEMENT.modelURL.equals(deviceNodeChild)) {
232 descriptor.modelURI = parseURI(XMLUtil.getTextContent(deviceNodeChild));
233 } else if (ELEMENT.presentationURL.equals(deviceNodeChild)) {
234 descriptor.presentationURI = parseURI(XMLUtil.getTextContent(deviceNodeChild));
235 } else if (ELEMENT.UPC.equals(deviceNodeChild)) {
236 descriptor.upc = XMLUtil.getTextContent(deviceNodeChild);
237 } else if (ELEMENT.serialNumber.equals(deviceNodeChild)) {
238 descriptor.serialNumber = XMLUtil.getTextContent(deviceNodeChild);
239 } else if (ELEMENT.UDN.equals(deviceNodeChild)) {
240 descriptor.udn = UDN.valueOf(XMLUtil.getTextContent(deviceNodeChild));
241 } else if (ELEMENT.iconList.equals(deviceNodeChild)) {
242 hydrateIconList(descriptor, deviceNodeChild);
243 } else if (ELEMENT.serviceList.equals(deviceNodeChild)) {
244 hydrateServiceList(descriptor, deviceNodeChild);
245 } else if (ELEMENT.deviceList.equals(deviceNodeChild)) {
246 hydrateDeviceList(descriptor, deviceNodeChild);
247 } else if (ELEMENT.X_DLNADOC.equals(deviceNodeChild) &&
248 Descriptor.Device.DLNA_PREFIX.equals(deviceNodeChild.getPrefix())) {
249 String txt = XMLUtil.getTextContent(deviceNodeChild);
250 try {
251 descriptor.dlnaDocs.add(DLNADoc.valueOf(txt));
252 } catch (InvalidValueException ex) {
253 log.info("Invalid X_DLNADOC value, ignoring value: " + txt);
254 }
255 } else if (ELEMENT.X_DLNACAP.equals(deviceNodeChild) &&
256 Descriptor.Device.DLNA_PREFIX.equals(deviceNodeChild.getPrefix())) {
257 descriptor.dlnaCaps = DLNACaps.valueOf(XMLUtil.getTextContent(deviceNodeChild));
258 }
259 }
260 }
261
262 public void hydrateIconList(MutableDevice descriptor, Node iconListNode) throws DescriptorBindingException {
263
264 NodeList iconListNodeChildren = iconListNode.getChildNodes();
265 for (int i = 0; i < iconListNodeChildren.getLength(); i++) {
266 Node iconListNodeChild = iconListNodeChildren.item(i);
267
268 if (iconListNodeChild.getNodeType() != Node.ELEMENT_NODE)
269 continue;
270
271 if (ELEMENT.icon.equals(iconListNodeChild)) {
272
273 MutableIcon icon = new MutableIcon();
274
275 NodeList iconChildren = iconListNodeChild.getChildNodes();
276
277 for (int x = 0; x < iconChildren.getLength(); x++) {
278 Node iconChild = iconChildren.item(x);
279
280 if (iconChild.getNodeType() != Node.ELEMENT_NODE)
281 continue;
282
283 if (ELEMENT.width.equals(iconChild)) {
284 icon.width = (Integer.valueOf(XMLUtil.getTextContent(iconChild)));
285 } else if (ELEMENT.height.equals(iconChild)) {
286 icon.height = (Integer.valueOf(XMLUtil.getTextContent(iconChild)));
287 } else if (ELEMENT.depth.equals(iconChild)) {
288 String depth = XMLUtil.getTextContent(iconChild);
289 try {
290 icon.depth = (Integer.valueOf(depth));
291 } catch(NumberFormatException ex) {
292 log.warning("Invalid icon depth '" + depth + "', using 16 as default: " + ex);
293 icon.depth = 16;
294 }
295 } else if (ELEMENT.url.equals(iconChild)) {
296 icon.uri = parseURI(XMLUtil.getTextContent(iconChild));
297 } else if (ELEMENT.mimetype.equals(iconChild)) {
298 try {
299 icon.mimeType = XMLUtil.getTextContent(iconChild);
300 MimeType.valueOf(icon.mimeType);
301 } catch(IllegalArgumentException ex) {
302 log.warning("Ignoring invalid icon mime type: " + icon.mimeType);
303 icon.mimeType = "";
304 }
305 }
306
307 }
308
309 descriptor.icons.add(icon);
310 }
311 }
312 }
313
314 public void hydrateServiceList(MutableDevice descriptor, Node serviceListNode) throws DescriptorBindingException {
315
316 NodeList serviceListNodeChildren = serviceListNode.getChildNodes();
317 for (int i = 0; i < serviceListNodeChildren.getLength(); i++) {
318 Node serviceListNodeChild = serviceListNodeChildren.item(i);
319
320 if (serviceListNodeChild.getNodeType() != Node.ELEMENT_NODE)
321 continue;
322
323 if (ELEMENT.service.equals(serviceListNodeChild)) {
324
325 NodeList serviceChildren = serviceListNodeChild.getChildNodes();
326
327 try {
328 MutableService service = new MutableService();
329
330 for (int x = 0; x < serviceChildren.getLength(); x++) {
331 Node serviceChild = serviceChildren.item(x);
332
333 if (serviceChild.getNodeType() != Node.ELEMENT_NODE)
334 continue;
335
336 if (ELEMENT.serviceType.equals(serviceChild)) {
337 service.serviceType = (ServiceType.valueOf(XMLUtil.getTextContent(serviceChild)));
338 } else if (ELEMENT.serviceId.equals(serviceChild)) {
339 service.serviceId = (ServiceId.valueOf(XMLUtil.getTextContent(serviceChild)));
340 } else if (ELEMENT.SCPDURL.equals(serviceChild)) {
341 service.descriptorURI = parseURI(XMLUtil.getTextContent(serviceChild));
342 } else if (ELEMENT.controlURL.equals(serviceChild)) {
343 service.controlURI = parseURI(XMLUtil.getTextContent(serviceChild));
344 } else if (ELEMENT.eventSubURL.equals(serviceChild)) {
345 service.eventSubscriptionURI = parseURI(XMLUtil.getTextContent(serviceChild));
346 }
347
348 }
349
350 descriptor.services.add(service);
351 } catch (InvalidValueException ex) {
352 log.warning(
353 "UPnP specification violation, skipping invalid service declaration. " + ex.getMessage()
354 );
355 }
356 }
357 }
358 }
359
360 public void hydrateDeviceList(MutableDevice descriptor, Node deviceListNode) throws DescriptorBindingException {
361
362 NodeList deviceListNodeChildren = deviceListNode.getChildNodes();
363 for (int i = 0; i < deviceListNodeChildren.getLength(); i++) {
364 Node deviceListNodeChild = deviceListNodeChildren.item(i);
365
366 if (deviceListNodeChild.getNodeType() != Node.ELEMENT_NODE)
367 continue;
368
369 if (ELEMENT.device.equals(deviceListNodeChild)) {
370 MutableDevice embeddedDevice = new MutableDevice();
371 embeddedDevice.parentDevice = descriptor;
372 descriptor.embeddedDevices.add(embeddedDevice);
373 hydrateDevice(embeddedDevice, deviceListNodeChild);
374 }
375 }
376
377 }
378
379 public String generate(Device deviceModel, RemoteClientInfo info, Namespace namespace) throws DescriptorBindingException {
380 try {
381 log.fine("Generating XML descriptor from device model: " + deviceModel);
382
383 return XMLUtil.documentToString(buildDOM(deviceModel, info, namespace));
384
385 } catch (Exception ex) {
386 throw new DescriptorBindingException("Could not build DOM: " + ex.getMessage(), ex);
387 }
388 }
389
390 public Document buildDOM(Device deviceModel, RemoteClientInfo info, Namespace namespace) throws DescriptorBindingException {
391
392 try {
393 log.fine("Generating DOM from device model: " + deviceModel);
394
395 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
396 factory.setNamespaceAware(true);
397
398 Document d = factory.newDocumentBuilder().newDocument();
399 generateRoot(namespace, deviceModel, d, info);
400
401 return d;
402
403 } catch (Exception ex) {
404 throw new DescriptorBindingException("Could not generate device descriptor: " + ex.getMessage(), ex);
405 }
406 }
407
408 protected void generateRoot(Namespace namespace, Device deviceModel, Document descriptor, RemoteClientInfo info) {
409
410 Element rootElement = descriptor.createElementNS(Descriptor.Device.NAMESPACE_URI, ELEMENT.root.toString());
411 descriptor.appendChild(rootElement);
412
413 generateSpecVersion(namespace, deviceModel, descriptor, rootElement);
414
415
416
417
418
419
420
421 generateDevice(namespace, deviceModel, descriptor, rootElement, info);
422 }
423
424 protected void generateSpecVersion(Namespace namespace, Device deviceModel, Document descriptor, Element rootElement) {
425 Element specVersionElement = appendNewElement(descriptor, rootElement, ELEMENT.specVersion);
426 appendNewElementIfNotNull(descriptor, specVersionElement, ELEMENT.major, deviceModel.getVersion().getMajor());
427 appendNewElementIfNotNull(descriptor, specVersionElement, ELEMENT.minor, deviceModel.getVersion().getMinor());
428 }
429
430 protected void generateDevice(Namespace namespace, Device deviceModel, Document descriptor, Element rootElement, RemoteClientInfo info) {
431
432 Element deviceElement = appendNewElement(descriptor, rootElement, ELEMENT.device);
433
434 appendNewElementIfNotNull(descriptor, deviceElement, ELEMENT.deviceType, deviceModel.getType());
435
436 DeviceDetails deviceModelDetails = deviceModel.getDetails(info);
437 appendNewElementIfNotNull(
438 descriptor, deviceElement, ELEMENT.friendlyName,
439 deviceModelDetails.getFriendlyName()
440 );
441 if (deviceModelDetails.getManufacturerDetails() != null) {
442 appendNewElementIfNotNull(
443 descriptor, deviceElement, ELEMENT.manufacturer,
444 deviceModelDetails.getManufacturerDetails().getManufacturer()
445 );
446 appendNewElementIfNotNull(
447 descriptor, deviceElement, ELEMENT.manufacturerURL,
448 deviceModelDetails.getManufacturerDetails().getManufacturerURI()
449 );
450 }
451 if (deviceModelDetails.getModelDetails() != null) {
452 appendNewElementIfNotNull(
453 descriptor, deviceElement, ELEMENT.modelDescription,
454 deviceModelDetails.getModelDetails().getModelDescription()
455 );
456 appendNewElementIfNotNull(
457 descriptor, deviceElement, ELEMENT.modelName,
458 deviceModelDetails.getModelDetails().getModelName()
459 );
460 appendNewElementIfNotNull(
461 descriptor, deviceElement, ELEMENT.modelNumber,
462 deviceModelDetails.getModelDetails().getModelNumber()
463 );
464 appendNewElementIfNotNull(
465 descriptor, deviceElement, ELEMENT.modelURL,
466 deviceModelDetails.getModelDetails().getModelURI()
467 );
468 }
469 appendNewElementIfNotNull(
470 descriptor, deviceElement, ELEMENT.serialNumber,
471 deviceModelDetails.getSerialNumber()
472 );
473 appendNewElementIfNotNull(descriptor, deviceElement, ELEMENT.UDN, deviceModel.getIdentity().getUdn());
474 appendNewElementIfNotNull(
475 descriptor, deviceElement, ELEMENT.presentationURL,
476 deviceModelDetails.getPresentationURI()
477 );
478 appendNewElementIfNotNull(
479 descriptor, deviceElement, ELEMENT.UPC,
480 deviceModelDetails.getUpc()
481 );
482
483 if (deviceModelDetails.getDlnaDocs() != null) {
484 for (DLNADoc dlnaDoc : deviceModelDetails.getDlnaDocs()) {
485 appendNewElementIfNotNull(
486 descriptor, deviceElement, Descriptor.Device.DLNA_PREFIX + ":" + ELEMENT.X_DLNADOC,
487 dlnaDoc, Descriptor.Device.DLNA_NAMESPACE_URI
488 );
489 }
490 }
491 appendNewElementIfNotNull(
492 descriptor, deviceElement, Descriptor.Device.DLNA_PREFIX + ":" + ELEMENT.X_DLNACAP,
493 deviceModelDetails.getDlnaCaps(), Descriptor.Device.DLNA_NAMESPACE_URI
494 );
495
496 appendNewElementIfNotNull(
497 descriptor, deviceElement, Descriptor.Device.SEC_PREFIX + ":" + ELEMENT.ProductCap,
498 deviceModelDetails.getSecProductCaps(), Descriptor.Device.SEC_NAMESPACE_URI
499 );
500
501 appendNewElementIfNotNull(
502 descriptor, deviceElement, Descriptor.Device.SEC_PREFIX + ":" + ELEMENT.X_ProductCap,
503 deviceModelDetails.getSecProductCaps(), Descriptor.Device.SEC_NAMESPACE_URI
504 );
505
506 generateIconList(namespace, deviceModel, descriptor, deviceElement);
507 generateServiceList(namespace, deviceModel, descriptor, deviceElement);
508 generateDeviceList(namespace, deviceModel, descriptor, deviceElement, info);
509 }
510
511 protected void generateIconList(Namespace namespace, Device deviceModel, Document descriptor, Element deviceElement) {
512 if (!deviceModel.hasIcons()) return;
513
514 Element iconListElement = appendNewElement(descriptor, deviceElement, ELEMENT.iconList);
515
516 for (Icon icon : deviceModel.getIcons()) {
517 Element iconElement = appendNewElement(descriptor, iconListElement, ELEMENT.icon);
518
519 appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.mimetype, icon.getMimeType());
520 appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.width, icon.getWidth());
521 appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.height, icon.getHeight());
522 appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.depth, icon.getDepth());
523 if (deviceModel instanceof RemoteDevice) {
524 appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.url, icon.getUri());
525 } else if (deviceModel instanceof LocalDevice) {
526 appendNewElementIfNotNull(descriptor, iconElement, ELEMENT.url, namespace.getIconPath(icon));
527 }
528 }
529 }
530
531 protected void generateServiceList(Namespace namespace, Device deviceModel, Document descriptor, Element deviceElement) {
532 if (!deviceModel.hasServices()) return;
533
534 Element serviceListElement = appendNewElement(descriptor, deviceElement, ELEMENT.serviceList);
535
536 for (Service service : deviceModel.getServices()) {
537 Element serviceElement = appendNewElement(descriptor, serviceListElement, ELEMENT.service);
538
539 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.serviceType, service.getServiceType());
540 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.serviceId, service.getServiceId());
541 if (service instanceof RemoteService) {
542 RemoteService rs = (RemoteService) service;
543 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.SCPDURL, rs.getDescriptorURI());
544 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.controlURL, rs.getControlURI());
545 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.eventSubURL, rs.getEventSubscriptionURI());
546 } else if (service instanceof LocalService) {
547 LocalService ls = (LocalService) service;
548 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.SCPDURL, namespace.getDescriptorPath(ls));
549 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.controlURL, namespace.getControlPath(ls));
550 appendNewElementIfNotNull(descriptor, serviceElement, ELEMENT.eventSubURL, namespace.getEventSubscriptionPath(ls));
551 }
552 }
553 }
554
555 protected void generateDeviceList(Namespace namespace, Device deviceModel, Document descriptor, Element deviceElement, RemoteClientInfo info) {
556 if (!deviceModel.hasEmbeddedDevices()) return;
557
558 Element deviceListElement = appendNewElement(descriptor, deviceElement, ELEMENT.deviceList);
559
560 for (Device device : deviceModel.getEmbeddedDevices()) {
561 generateDevice(namespace, device, descriptor, deviceListElement, info);
562 }
563 }
564
565 public void warning(SAXParseException e) throws SAXException {
566 log.warning(e.toString());
567 }
568
569 public void error(SAXParseException e) throws SAXException {
570 throw e;
571 }
572
573 public void fatalError(SAXParseException e) throws SAXException {
574 throw e;
575 }
576
577 static protected URI parseURI(String uri) {
578
579
580 if (uri.startsWith("www.")) {
581 uri = "http://" + uri;
582 }
583
584
585
586 if (uri.contains(" ")) {
587
588
589
590 uri = uri.replaceAll(" ", "%20");
591 }
592
593 try {
594 return URI.create(uri);
595 } catch (Throwable ex) {
596
597
598
599
600
601
602
603
604
605
606
607 log.fine("Illegal URI, trying with ./ prefix: " + Exceptions.unwrap(ex));
608
609 }
610 try {
611
612
613
614
615
616
617
618 return URI.create("./" + uri);
619 } catch (IllegalArgumentException ex) {
620 log.warning("Illegal URI '" + uri + "', ignoring value: " + Exceptions.unwrap(ex));
621
622 }
623 return null;
624 }
625
626 }