1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package example.mediaserver;
16
17 import org.fourthline.cling.binding.annotations.AnnotationLocalServiceBinder;
18 import org.fourthline.cling.controlpoint.ActionCallback;
19 import org.fourthline.cling.model.DefaultServiceManager;
20 import org.fourthline.cling.model.action.ActionInvocation;
21 import org.fourthline.cling.model.message.UpnpResponse;
22 import org.fourthline.cling.model.meta.LocalService;
23 import org.fourthline.cling.model.meta.Service;
24 import org.fourthline.cling.support.contentdirectory.AbstractContentDirectoryService;
25 import org.fourthline.cling.support.contentdirectory.ContentDirectoryErrorCode;
26 import org.fourthline.cling.support.contentdirectory.ContentDirectoryException;
27 import org.fourthline.cling.support.contentdirectory.DIDLParser;
28 import org.fourthline.cling.support.contentdirectory.callback.Browse;
29 import org.fourthline.cling.support.model.BrowseFlag;
30 import org.fourthline.cling.support.model.BrowseResult;
31 import org.fourthline.cling.support.model.DIDLContent;
32 import org.fourthline.cling.support.model.DIDLObject;
33 import org.fourthline.cling.support.model.PersonWithRole;
34 import org.fourthline.cling.support.model.Res;
35 import org.fourthline.cling.support.model.SortCriterion;
36 import org.fourthline.cling.support.model.item.Item;
37 import org.fourthline.cling.support.model.item.MusicTrack;
38 import org.seamless.util.io.IO;
39 import org.seamless.util.MimeType;
40 import org.testng.annotations.Test;
41
42 import java.io.InputStream;
43
44 import static org.testng.Assert.assertEquals;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public class ContentDirectoryBrowseTest {
61
62 protected DIDLParser parser = new DIDLParser();
63
64 @Test
65 public void browseRootMetadata() {
66
67 final boolean[] assertions = new boolean[3];
68 new Browse(createService(), "0", BrowseFlag.METADATA) {
69 @Override
70 public void received(ActionInvocation actionInvocation, DIDLContent didl) {
71 assertEquals(didl.getContainers().size(), 1);
72 assertEquals(didl.getContainers().get(0).getTitle(), "My multimedia stuff");
73 assertions[0] = true;
74 }
75
76 @Override
77 public void updateStatus(Status status) {
78 if (!assertions[1] && status.equals(Status.LOADING)) {
79 assertions[1] = true;
80 } else if (assertions[1] && !assertions[2] && status.equals(Status.OK)) {
81 assertions[2] = true;
82 }
83 }
84
85 @Override
86 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
87
88 }
89 }.run();
90
91 for (boolean assertion : assertions) {
92 assertEquals(assertion, true);
93 }
94 }
95
96 @Test
97 public void browseRootChildren() {
98
99 final boolean[] assertions = new boolean[3];
100 new Browse(
101 createService(), "0", BrowseFlag.DIRECT_CHILDREN, "foo", 1, 10l,
102 new SortCriterion(true, "dc:title"), new SortCriterion(false, "dc:creator")
103 ) {
104 public void received(ActionInvocation actionInvocation, DIDLContent didl) {
105 assertEquals(didl.getContainers().size(), 3);
106 assertEquals(didl.getContainers().get(0).getTitle(), "My Music");
107 assertEquals(didl.getContainers().get(1).getTitle(), "My Photos");
108 assertEquals(didl.getContainers().get(2).getTitle(), "Album Art");
109 assertions[0] = true;
110 }
111
112 @Override
113 public void updateStatus(Status status) {
114 if (!assertions[1] && status.equals(Status.LOADING)) {
115 assertions[1] = true;
116 } else if (assertions[1] && !assertions[2] && status.equals(Status.OK)) {
117 assertions[2] = true;
118 }
119 }
120
121 @Override
122 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
123 }
124 }.run();
125
126 for (boolean assertion : assertions) {
127 assertEquals(assertion, true);
128 }
129 }
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 @Test
170 public void browseTracks() {
171
172 final boolean[] assertions = new boolean[3];
173
174 Service service = createService();
175
176 ActionCallback simpleBrowseAction =
177 new Browse(service, "3", BrowseFlag.DIRECT_CHILDREN) {
178
179 @Override
180 public void received(ActionInvocation actionInvocation, DIDLContent didl) {
181
182
183 assertEquals(didl.getItems().size(), 2);
184 Item item1 = didl.getItems().get(0);
185 assertEquals(
186 item1.getTitle(),
187 "All Secrets Known"
188 );
189 assertEquals(
190 item1.getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM.class),
191 "Black Gives Way To Blue"
192 );
193 assertEquals(
194 item1.getFirstResource().getProtocolInfo().getContentFormatMimeType().toString(),
195 "audio/mpeg"
196 );
197 assertEquals(
198 item1.getFirstResource().getValue(),
199 "http://10.0.0.1/files/101.mp3"
200 );
201
202
203 assert MusicTrack.CLASS.equals(item1);
204 MusicTrack track1 = (MusicTrack) item1;
205 assertEquals(track1.getTitle(), "All Secrets Known");
206 assertEquals(track1.getAlbum(), "Black Gives Way To Blue");
207 assertEquals(track1.getFirstArtist().getName(), "Alice In Chains");
208 assertEquals(track1.getFirstArtist().getRole(), "Performer");
209
210 MusicTrack track2 = (MusicTrack) didl.getItems().get(1);
211 assertEquals(track2.getTitle(), "Check My Brain");
212
213
214
215
216 assertions[0] = true;
217
218 }
219
220 @Override
221 public void updateStatus(Status status) {
222
223
224 if (!assertions[1] && status.equals(Status.LOADING)) {
225 assertions[1] = true;
226 } else if (assertions[1] && !assertions[2] && status.equals(Status.OK)) {
227 assertions[2] = true;
228 }
229
230 }
231
232 @Override
233 public void failure(ActionInvocation invocation,
234 UpnpResponse operation,
235 String defaultMsg) {
236
237 }
238 };
239
240
241 ActionCallback complexBrowseAction =
242 new Browse(service, "3", BrowseFlag.DIRECT_CHILDREN,
243 "*",
244 100l, 50l,
245 new SortCriterion(true, "dc:title"),
246 new SortCriterion(false, "dc:creator")) {
247
248
249
250
251 @Override
252 public void received(ActionInvocation actionInvocation, DIDLContent didl) {
253
254 }
255
256 @Override
257 public void updateStatus(Status status) {
258
259 }
260
261 @Override
262 public void failure(ActionInvocation invocation, UpnpResponse operation, String defaultMsg) {
263 }
264
265 };
266
267 simpleBrowseAction.run();
268
269 for (boolean assertion : assertions) {
270 assertEquals(assertion, true);
271 }
272 }
273
274 public Service createService() {
275 LocalService<AbstractContentDirectoryService> service =
276 new AnnotationLocalServiceBinder().read(AbstractContentDirectoryService.class);
277 service.setManager(
278 new DefaultServiceManager<AbstractContentDirectoryService>(service, null) {
279 @Override
280 protected AbstractContentDirectoryService createServiceInstance() throws Exception {
281 return new MP3ContentDirectory();
282 }
283 }
284 );
285 return service;
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315 public class MP3ContentDirectory extends AbstractContentDirectoryService {
316
317 @Override
318 public BrowseResult browse(String objectID, BrowseFlag browseFlag,
319 String filter,
320 long firstResult, long maxResults,
321 SortCriterion[] orderby) throws ContentDirectoryException {
322 try {
323
324 if (objectID.equals("0") && browseFlag.equals(BrowseFlag.METADATA)) {
325
326 assertEquals(firstResult, 0);
327 assertEquals(maxResults, 999);
328
329 assertEquals(orderby.length, 0);
330
331 String result = readResource("org/fourthline/cling/test/support/contentdirectory/samples/browseRoot.xml");
332 return new BrowseResult(result, 1, 1);
333
334 } else if (objectID.equals("0") && browseFlag.equals(BrowseFlag.DIRECT_CHILDREN)) {
335
336 assertEquals(filter, "foo");
337 assertEquals(firstResult, 1);
338 assertEquals(maxResults, 10l);
339
340 assertEquals(orderby.length, 2);
341 assertEquals(orderby[0].isAscending(), true);
342 assertEquals(orderby[0].getPropertyName(), "dc:title");
343 assertEquals(orderby[1].isAscending(), false);
344 assertEquals(orderby[1].getPropertyName(), "dc:creator");
345
346 String result = readResource("org/fourthline/cling/test/support/contentdirectory/samples/browseRootChildren.xml");
347 return new BrowseResult(result, 3, 3);
348 }
349
350
351
352
353 DIDLContent didl = new DIDLContent();
354
355 String album = ("Black Gives Way To Blue");
356 String creator = "Alice In Chains";
357 PersonWithRole artist = new PersonWithRole(creator, "Performer");
358 MimeType mimeType = new MimeType("audio", "mpeg");
359
360 didl.addItem(new MusicTrack(
361 "101", "3",
362 "All Secrets Known",
363 creator, album, artist,
364 new Res(mimeType, 123456l, "00:03:25", 8192l, "http://10.0.0.1/files/101.mp3")
365 ));
366
367 didl.addItem(new MusicTrack(
368 "102", "3",
369 "Check My Brain",
370 creator, album, artist,
371 new Res(mimeType, 2222222l, "00:04:11", 8192l, "http://10.0.0.1/files/102.mp3")
372 ));
373
374
375
376
377 return new BrowseResult(new DIDLParser().generate(didl), 2, 2);
378
379 } catch (Exception ex) {
380 throw new ContentDirectoryException(
381 ContentDirectoryErrorCode.CANNOT_PROCESS,
382 ex.toString()
383 );
384 }
385 }
386
387 @Override
388 public BrowseResult search(String containerId,
389 String searchCriteria, String filter,
390 long firstResult, long maxResults,
391 SortCriterion[] orderBy) throws ContentDirectoryException {
392
393 return super.search(containerId, searchCriteria, filter, firstResult, maxResults, orderBy);
394 }
395 }
396
397 protected String readResource(String resource) {
398 InputStream is = null;
399 try {
400 is = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
401 return IO.readLines(is);
402 } catch (Exception ex) {
403 throw new RuntimeException(ex);
404 } finally {
405 try {
406 if (is != null) is.close();
407 } catch (Exception ex) {
408
409 }
410 }
411 }
412
413 }