View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.protocol.sync;
17  
18  import org.fourthline.cling.UpnpService;
19  import org.fourthline.cling.binding.xml.DescriptorBindingException;
20  import org.fourthline.cling.binding.xml.DeviceDescriptorBinder;
21  import org.fourthline.cling.binding.xml.ServiceDescriptorBinder;
22  import org.fourthline.cling.model.message.StreamRequestMessage;
23  import org.fourthline.cling.model.message.StreamResponseMessage;
24  import org.fourthline.cling.model.message.UpnpResponse;
25  import org.fourthline.cling.model.message.header.ContentTypeHeader;
26  import org.fourthline.cling.model.message.header.ServerHeader;
27  import org.fourthline.cling.model.message.header.UpnpHeader;
28  import org.fourthline.cling.model.meta.Icon;
29  import org.fourthline.cling.model.meta.LocalDevice;
30  import org.fourthline.cling.model.meta.LocalService;
31  import org.fourthline.cling.model.resource.DeviceDescriptorResource;
32  import org.fourthline.cling.model.resource.IconResource;
33  import org.fourthline.cling.model.resource.Resource;
34  import org.fourthline.cling.model.resource.ServiceDescriptorResource;
35  import org.fourthline.cling.protocol.ReceivingSync;
36  import org.fourthline.cling.transport.RouterException;
37  import org.seamless.util.Exceptions;
38  
39  import java.net.URI;
40  import java.util.logging.Level;
41  import java.util.logging.Logger;
42  
43  /**
44   * Handles reception of device/service descriptor and icon retrieval messages.
45   *
46   * <p>
47   * Requested device and service XML descriptors are generated on-the-fly for every request.
48   * </p>
49   * <p>
50   * Descriptor XML is dynamically generated depending on the control point - some control
51   * points require different metadata than others for the same device and services.
52   * </p>
53   *
54   * @author Christian Bauer
55   */
56  public class ReceivingRetrieval extends ReceivingSync<StreamRequestMessage, StreamResponseMessage> {
57  
58      final private static Logger log = Logger.getLogger(ReceivingRetrieval.class.getName());
59  
60      public ReceivingRetrieval(UpnpService upnpService, StreamRequestMessage inputMessage) {
61          super(upnpService, inputMessage);
62      }
63  
64      protected StreamResponseMessage executeSync() throws RouterException {
65  
66          if (!getInputMessage().hasHostHeader()) {
67              log.fine("Ignoring message, missing HOST header: " + getInputMessage());
68              return new StreamResponseMessage(new UpnpResponse(UpnpResponse.Status.PRECONDITION_FAILED));
69          }
70  
71          URI requestedURI = getInputMessage().getOperation().getURI();
72  
73          Resource foundResource = getUpnpService().getRegistry().getResource(requestedURI);
74  
75          if (foundResource == null) {
76              foundResource = onResourceNotFound(requestedURI);
77              if (foundResource == null) {
78                  log.fine("No local resource found: " + getInputMessage());
79                  return null;
80              }
81          }
82  
83          return createResponse(requestedURI, foundResource);
84      }
85  
86      protected StreamResponseMessage createResponse(URI requestedURI, Resource resource) {
87  
88          StreamResponseMessage response;
89  
90          try {
91  
92              if (DeviceDescriptorResource.class.isAssignableFrom(resource.getClass())) {
93  
94                  log.fine("Found local device matching relative request URI: " + requestedURI);
95                  LocalDevice device = (LocalDevice) resource.getModel();
96  
97                  DeviceDescriptorBinder deviceDescriptorBinder =
98                          getUpnpService().getConfiguration().getDeviceDescriptorBinderUDA10();
99                  String deviceDescriptor = deviceDescriptorBinder.generate(
100                         device,
101                         getRemoteClientInfo(),
102                         getUpnpService().getConfiguration().getNamespace()
103                 );
104                 response = new StreamResponseMessage(
105                         deviceDescriptor,
106                         new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE)
107                 );
108             } else if (ServiceDescriptorResource.class.isAssignableFrom(resource.getClass())) {
109 
110 
111                 log.fine("Found local service matching relative request URI: " + requestedURI);
112                 LocalService service = (LocalService) resource.getModel();
113 
114                 ServiceDescriptorBinder serviceDescriptorBinder =
115                         getUpnpService().getConfiguration().getServiceDescriptorBinderUDA10();
116                 String serviceDescriptor = serviceDescriptorBinder.generate(service);
117                 response = new StreamResponseMessage(
118                         serviceDescriptor,
119                         new ContentTypeHeader(ContentTypeHeader.DEFAULT_CONTENT_TYPE)
120                 );
121 
122             } else if (IconResource.class.isAssignableFrom(resource.getClass())) {
123 
124                 log.fine("Found local icon matching relative request URI: " + requestedURI);
125                 Icon icon = (Icon) resource.getModel();
126                 response = new StreamResponseMessage(icon.getData(), icon.getMimeType());
127 
128             } else {
129 
130                 log.fine("Ignoring GET for found local resource: " + resource);
131                 return null;
132             }
133 
134         } catch (DescriptorBindingException ex) {
135             log.warning("Error generating requested device/service descriptor: " + ex.toString());
136             log.log(Level.WARNING, "Exception root cause: ", Exceptions.unwrap(ex));
137             response = new StreamResponseMessage(UpnpResponse.Status.INTERNAL_SERVER_ERROR);
138         }
139         
140         response.getHeaders().add(UpnpHeader.Type.SERVER, new ServerHeader());
141 
142         return response;
143     }
144 
145     /**
146      * Called if the {@link org.fourthline.cling.registry.Registry} had no result.
147      *
148      * @param requestedURIPath The requested URI path
149      * @return <code>null</code> or your own {@link Resource}
150      */
151     protected Resource onResourceNotFound(URI requestedURIPath) {
152         return null;
153     }
154 }