Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *  Purpose: To test the MetaCatURL class by JUnit
6
 *    Authors: Jing Tao
7
 *
8
 *   '$Author: tao $'
9
 *     '$Date: 2014-03-04 09:48:15 -0800 (Tue, 04 Mar 2014) $'
10
 * '$Revision: 8695 $'
11
 *
12
 * This program is free software; you can redistribute it and/or modify
13
 * it under the terms of the GNU General Public License as published by
14
 * the Free Software Foundation; either version 2 of the License, or
15
 * (at your option) any later version.
16
 *
17
 * This program is distributed in the hope that it will be useful,
18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
 * GNU General Public License for more details.
21
 *
22
 * You should have received a copy of the GNU General Public License
23
 * along with this program; if not, write to the Free Software
24
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
 */
26

    
27
package edu.ucsb.nceas.metacattest;
28

    
29
import edu.ucsb.nceas.MCTestCase;
30
import edu.ucsb.nceas.metacat.IdentifierManager;
31
import edu.ucsb.nceas.metacat.properties.PropertyService;
32
import edu.ucsb.nceas.utilities.HttpMessage;
33
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
34

    
35
import junit.framework.Test;
36
import junit.framework.TestSuite;
37

    
38
import java.io.*;
39
import java.net.*;
40
import java.util.*;
41

    
42

    
43
/**
44
 * A JUnit test for testing Step class processing
45
 */
46
public class MetaCatServletTest extends MCTestCase {
47
	private static String metacatURL;
48
	private String serialNumber;
49

    
50
	/* Initialize properties */
51
	static {
52
		try {
53
			metacatURL = PropertyService.getProperty("test.metacatUrl");
54
		} catch (PropertyNotFoundException pnfe) {
55
			System.err.println("Could not get property in static block: "
56
					+ pnfe.getMessage());
57
		}
58
	}
59

    
60
	/**
61
	 * Constructor to build the test
62
	 * 
63
	 * @param name
64
	 *            the name of the test method
65
	 */
66
	public MetaCatServletTest(String name) {
67
		super(name);
68
	}
69

    
70
	/**
71
	 * Constructor to build the test
72
	 * 
73
	 * @param name
74
	 *            the name of the test method
75
	 */
76
	public MetaCatServletTest(String name, String serial) {
77
		super(name);
78
		serialNumber = serial;
79
	}
80

    
81
	/**
82
	 * Establish a testing framework by initializing appropriate objects
83
	 */
84
	public void setUp() {
85

    
86
	}
87

    
88
	/**
89
	 * Release any objects after tests are complete
90
	 */
91
	public void tearDown() {
92
	}
93

    
94
	/**
95
	 * Create a suite of tests to be run together
96
	 */
97
	public static Test suite() {
98
		double number = 0;
99
		String serial = null;
100

    
101
		TestSuite suite = new TestSuite();
102
		suite.addTest(new MetaCatServletTest("initialize"));
103
		suite.addTest(new MetaCatServletTest("testLterReferralLogin"));
104
		suite.addTest(new MetaCatServletTest("testLterReferralLoginFail"));
105
		suite.addTest(new MetaCatServletTest("testOtherReferralLogin"));
106
		suite.addTest(new MetaCatServletTest("testOtherReferralLoginFail"));
107
		suite.addTest(new MetaCatServletTest("testNCEASLoginFail"));
108
		// Should put a login successfully at the end of login test
109
		// So insert or update can have cookie.
110
		suite.addTest(new MetaCatServletTest("testNCEASLogin"));
111

    
112
		// create random number for docid, so it can void repeat
113
		number = Math.random() * 100000;
114
		serial = Integer.toString(((new Double(number)).intValue()));
115
		debug("serial: " + serial);
116
		suite.addTest(new MetaCatServletTest("testInsertXMLDocument", serial));
117
		suite.addTest(new MetaCatServletTest("testReadXMLDocumentXMLFormat", serial));
118
		suite.addTest(new MetaCatServletTest("testUpdateXMLDocument", serial));
119

    
120
		suite.addTest(new MetaCatServletTest("testReadXMLDocumentHTMLFormat", serial));
121
		suite.addTest(new MetaCatServletTest("testReadXMLDocumentZipFormat", serial));
122

    
123
		suite.addTest(new MetaCatServletTest("testDeleteXMLDocument", serial));
124
	
125
		// insert invalid xml document
126
		number = Math.random() * 100000;
127
		serial = Integer.toString(((new Double(number)).intValue()));
128
		suite.addTest(new MetaCatServletTest("testInsertInvalidateXMLDocument", serial));
129
		// insert non well formed document
130
		number = Math.random() * 100000;
131
		serial = Integer.toString(((new Double(number)).intValue()));
132
		suite
133
				.addTest(new MetaCatServletTest("testInsertNonWellFormedXMLDocument",
134
						serial));
135

    
136
		suite.addTest(new MetaCatServletTest("testLogOut"));
137
		
138
		suite.addTest(new MetaCatServletTest("testReindexFail"));
139
		
140
		suite.addTest(new MetaCatServletTest("testPiscoReferralLogin"));
141
		
142
		suite.addTest(new MetaCatServletTest("testPiscoReferralLoginFail"));
143
		
144
		return suite;
145
	}
146

    
147
	/**
148
	 * Run an initial test that always passes to check that the test harness is
149
	 * working.
150
	 */
151
	public void initialize() {
152
		assertTrue(1 == 1);
153
	}
154

    
155
	/**
156
	 * Test the login to neceas succesfully
157
	 */
158
    public void testNCEASLogin() {
159
        debug("\nRunning: testNCEASLogin test");
160
        try {
161
            String user = PropertyService.getProperty("test.mcUser");
162
            String passwd = PropertyService.getProperty("test.mcPassword");
163
            assertTrue(logIn(user, passwd));
164
        } catch (PropertyNotFoundException pnfe) {
165
            fail("Could not find property: " + pnfe.getMessage());
166
        }
167
    }
168

    
169
	/**
170
	 * Test the login to neceas failed
171
	 */
172
	public void testNCEASLoginFail() {
173
		debug("\nRunning: testNCEASLoginFail test");
174
        try {
175
            String user = PropertyService.getProperty("test.mcUser");
176
            String passwd = "BogusPasswordShouldFail";
177
            assertTrue(!logIn(user, passwd));
178
        } catch (PropertyNotFoundException pnfe) {
179
            fail("Could not find property: " + pnfe.getMessage());
180
        }
181
	}
182

    
183
	/**
184
	 * Test the login to lter succesfully
185
	 */
186
	public void testLterReferralLogin() {
187
		debug("\nRunning: testLterReferralLogin test");
188
		String user = null;
189
		String passwd = null;
190
		try {
191
			user = PropertyService.getProperty("test.lterUser");
192
			passwd = PropertyService.getProperty("test.lterPassword");
193
		} catch (PropertyNotFoundException pnfe) {
194
			fail("Could not find property: " + pnfe.getMessage());
195
		}
196

    
197
		debug("Logging into lter: " + user + " : " + passwd);
198
		assertTrue(logIn(user, passwd));
199

    
200
	}
201

    
202
	/**
203
	 * Test the login to lter failed
204
	 */
205
	public void testLterReferralLoginFail() {
206
		debug("\nRunning: testLterReferralLoginFail test");
207
		String user = null;
208
    String passwd = "wrong";
209
    try {
210
      user = PropertyService.getProperty("test.lterUser");
211
    } catch (PropertyNotFoundException pnfe) {
212
      fail("Could not find property: " + pnfe.getMessage());
213
    }
214
		assertTrue(!logIn(user, passwd));
215
		// assertTrue( withProtocol.getProtocol().equals("http"));
216
	}
217

    
218
	/**
219
	 * Test the login to Other succesfully
220
	 */
221
	public void testOtherReferralLogin() {
222
		debug("\nRunning: testOtherReferralLogin test");
223
		String user = null;
224
		String passwd = null;
225
		try {
226
			user = PropertyService.getProperty("test.referralUser");
227
			passwd = PropertyService.getProperty("test.referralPassword");
228
		} catch (PropertyNotFoundException pnfe) {
229
			fail("Could not find property: " + pnfe.getMessage());
230
		}
231
		debug("logging in Other user: " + user + ":" + passwd);
232
		assertTrue(logIn(user, passwd));
233
		// assertTrue( withProtocol.getProtocol().equals("http"));
234
	}
235

    
236
	/**
237
	 * Test the login to Other failed
238
	 */
239
	public void testOtherReferralLoginFail() {
240
		debug("\nRunning: testOtherReferralLoginFail test");
241
		String user = null;
242
    String passwd = "wrong";
243
    try {
244
      user = PropertyService.getProperty("test.referralUser");
245
    } catch (PropertyNotFoundException pnfe) {
246
      fail("Could not find property: " + pnfe.getMessage());
247
    }
248
		assertTrue(!logIn(user, passwd));
249
		// assertTrue( withProtocol.getProtocol().equals("http"));
250
	}
251
	
252
	/**
253
     * Test the login to Other succesfully
254
     */
255
    public void testPiscoReferralLogin() {
256
        debug("\nRunning: testPiscoReferralLogin test");
257
        String user = piscouser;
258
        String passwd = piscopassword;
259
        debug("logging in pisco user: " + user + ":" + passwd);
260
        assertTrue(logIn(user, passwd));
261
        // assertTrue( withProtocol.getProtocol().equals("http"));
262
    }
263

    
264
    /**
265
     * Test the login to Other failed
266
     */
267
    public void testPiscoReferralLoginFail() {
268
        debug("\nRunning: testPiscoReferralLoginFail test");
269
        String user = piscouser;
270
        String passwd = "wrong";
271
        assertTrue(!logIn(user, passwd));
272
        // assertTrue( withProtocol.getProtocol().equals("http"));
273
    }
274

    
275
	/**
276
	 * Test insert a xml document successfully
277
	 */
278
    public void testInsertXMLDocument() {
279
        debug("\nRunning: testInsertXMLDocument test");
280
        String name = null;
281
        try {
282
            String user = PropertyService.getProperty("test.mcUser");
283
            String passwd = PropertyService.getProperty("test.mcPassword");
284

    
285
            name = "john" + PropertyService.getProperty("document.accNumSeparator") + serialNumber + PropertyService.getProperty("document.accNumSeparator")
286
                    + "1";
287
            debug("insert docid: " + name);
288
            String content = "<?xml version=\"1.0\"?>" + "<!DOCTYPE acl PUBLIC \"-//ecoinformatics.org//"
289
                    + "eml-access-2.0.0beta6//EN\" \"http://pine.nceas.ucsb.edu:8080/tao/dtd/eml-access-2.0.0beta6.dtd\">"
290
                    + "<acl authSystem=\"knb\" order=\"allowFirst\">" + "<identifier>" + name + "</identifier>" + "<allow>" + "<principal>" + user
291
                    + "</principal>" + "<permission>all</permission>" + "</allow>" + "<allow>" + "<principal>public</principal>"
292
                    + "<permission>read</permission>" + "</allow>" + "</acl>";
293
            debug("xml document: " + content);
294
            assertTrue(handleXMLDocument(content, name, "insert"));
295
        } catch (PropertyNotFoundException pnfe) {
296
            fail("Could not find property: " + pnfe.getMessage());
297
        }
298
    }
299

    
300
	/**
301
	 * Test insert a invalidate xml document successfully In the String, there
302
	 * is no <!Doctype ... Public/System/>
303
	 */
304
    public void testInsertInvalidateXMLDocument() {
305
        debug("\nRunning: testInsertInvalidateXMLDocument test");
306
        String name = null;
307
        try {
308
            String user = PropertyService.getProperty("test.mcUser");
309
            String passwd = PropertyService.getProperty("test.mcPassword");
310

    
311
            name = "john" + PropertyService.getProperty("document.accNumSeparator") + serialNumber + PropertyService.getProperty("document.accNumSeparator")
312
                    + "1";
313
            debug("insert docid: " + name);
314
            String content = "<?xml version=\"1.0\"?>" + "<acl authSystem=\"knb\" order=\"allowFirst\">" + "<identifier>" + name + "</identifier>" + "<allow>"
315
                    + "<principal>" + user + "</principal>" + "<permission>all</permission>" + "</allow>" + "<allow>" + "<principal>public</principal>"
316
                    + "<permission>read</permission>" + "</allow>" + "</acl>";
317
            debug("xml document: " + content);
318
            assertTrue(handleXMLDocument(content, name, "insert"));
319
        } catch (PropertyNotFoundException pnfe) {
320
            fail("Could not find property: " + pnfe.getMessage());
321
        }
322
    }
323

    
324
	/**
325
	 * Test insert a non well-formed xml document successfully There is no
326
	 * </acl> in this string
327
	 */
328
    public void testInsertNonWellFormedXMLDocument() {
329
        debug("\nRunning: testInsertNonWellFormedXMLDocument test");
330
        String name = null;
331
        try {
332
            String user = PropertyService.getProperty("test.mcUser");
333
            String passwd = PropertyService.getProperty("test.mcPassword");
334

    
335
            name = "john" + PropertyService.getProperty("document.accNumSeparator") + serialNumber + PropertyService.getProperty("document.accNumSeparator")
336
                    + "1";
337
            debug("insert non well-formed docid: " + name);
338
            String content = "<?xml version=\"1.0\"?>" + "<acl authSystem=\"knb\" order=\"allowFirst\">" + "<identifier>" + name + "</identifier>" + "<allow>"
339
                    + "<principal>" + user + "</principal>" + "<permission>all</permission>" + "</allow>" + "<allow>" + "<principal>public</principal>"
340
                    + "<permission>read</permission>" + "</allow>";
341

    
342
            debug("xml document: " + content);
343
            assertTrue(!handleXMLDocument(content, name, "insert"));
344
        } catch (PropertyNotFoundException pnfe) {
345
            fail("Could not find property: " + pnfe.getMessage());
346
        }
347
    }
348

    
349
	/**
350
	 * Test read a xml document in xml format successfully
351
	 */
352
	public void testReadXMLDocumentXMLFormat() {
353
		debug("\nRunning: testReadXMLDocumentXMLFormat test");
354
		String name = null;
355
		try {
356
			name = "john" + PropertyService.getProperty("document.accNumSeparator")
357
					+ serialNumber
358
					+ PropertyService.getProperty("document.accNumSeparator") + "1";
359
		} catch (PropertyNotFoundException pnfe) {
360
			fail("Could not find property: " + pnfe.getMessage());
361
		}
362
		assertTrue(handleReadAction(name, "xml"));
363

    
364
	}
365

    
366
	/**
367
	 * Test read a xml document in html format successfully
368
	 */
369
	public void testReadXMLDocumentHTMLFormat() {
370
		debug("\nRunning: testReadXMLDocumentHTMLFormat test");
371
		String name = null;
372
		try {
373
			name = "john" + PropertyService.getProperty("document.accNumSeparator")
374
					+ serialNumber
375
					+ PropertyService.getProperty("document.accNumSeparator") + "1";
376
		} catch (PropertyNotFoundException pnfe) {
377
			fail("Could not find property: " + pnfe.getMessage());
378
		}
379
		assertTrue(handleReadAction(name, "html"));
380

    
381
	}
382

    
383
	/**
384
	 * Test read a xml document in zip format successfully
385
	 */
386
	public void testReadXMLDocumentZipFormat() {
387
		debug("\nRunning: testReadXMLDocumentZipFormat test");
388
		String name = null;
389
		try {
390
			name = "john" + PropertyService.getProperty("document.accNumSeparator")
391
					+ serialNumber
392
					+ PropertyService.getProperty("document.accNumSeparator") + "1";
393
		} catch (PropertyNotFoundException pnfe) {
394
			fail("Could not find property: " + pnfe.getMessage());
395
		}
396
		assertTrue(handleReadAction(name, "zip"));
397

    
398
	}
399

    
400
	/**
401
	 * Test insert a xml document successfully
402
	 */
403
    public void testUpdateXMLDocument() {
404
        debug("\nRunning: testUpdateXMLDocument test");
405
        String name = null;
406
        try {
407
            String user = PropertyService.getProperty("test.mcUser");
408
            String passwd = PropertyService.getProperty("test.mcPassword");
409

    
410
            name = "john" + PropertyService.getProperty("document.accNumSeparator") + serialNumber + PropertyService.getProperty("document.accNumSeparator")
411
                    + "2";
412
            debug("update docid: " + name);
413
            String content = "<?xml version=\"1.0\"?>" + "<!DOCTYPE acl PUBLIC \"-//ecoinformatics.org//"
414
                    + "eml-access-2.0.0beta6//EN\" \"http://pine.nceas.ucsb." + "edu:8080/tao/dtd/eml-access-2.0.0beta6.dtd\">"
415
                    + "<acl authSystem=\"knb\" order=\"allowFirst\">" + "<identifier>" + name + "</identifier>" + "<allow>" + "<principal>" + user
416
                    + "</principal>" + "<permission>all</permission>" + "</allow>" + "<allow>" + "<principal>public</principal>"
417
                    + "<permission>read</permission>" + "</allow>" + "</acl>";
418
            debug("xml document: " + content);
419
            assertTrue(handleXMLDocument(content, name, "update"));
420
        } catch (PropertyNotFoundException pnfe) {
421
            fail("Could not find property: " + pnfe.getMessage());
422
        }
423
    }
424

    
425
	/**
426
	 * Test delete a xml document successfully
427
	 */
428
	public void testDeleteXMLDocument() {
429
		debug("\nRunning: testDeleteXMLDocument test");
430
		String name = null;
431
		try {
432
			name = "john" + PropertyService.getProperty("document.accNumSeparator")
433
					+ serialNumber
434
					+ PropertyService.getProperty("document.accNumSeparator") + "2";
435
		} catch (PropertyNotFoundException pnfe) {
436
			fail("Could not find property: " + pnfe.getMessage());
437
		}
438
		debug("delete docid: " + name);
439
		assertTrue(handleDeleteFile(name));
440

    
441
	}
442

    
443
    
444
	/**
445
	 * Test logout action
446
	 */
447
	public void testLogOut() {
448
		debug("\nRunning: testLogOut test");
449
		assertTrue(handleLogOut());
450

    
451
	}
452
	
453
	public void testReindexFail() {
454

    
455
		// find a pid to reindex
456
		String identifier = null;
457
		List<String> ids = IdentifierManager.getInstance().getAllSystemMetadataGUIDs();
458
		if (ids != null && !ids.isEmpty()) {
459
			identifier = ids.get(0);
460
		}
461
		Properties prop = new Properties();
462
		prop.put("action", "reindex");
463
		prop.put("pid", identifier);
464

    
465
		String message = getMetacatString(prop);
466
		debug("Reindex Message: " + message);
467
		if (message.indexOf("<error>") != -1) {// there was an error
468
			assertTrue(true);
469
		} else if (message.indexOf("<success>") != -1) {
470
			fail("Unauthenticated user should not be able to invoke this action: " + message);
471
		} else {// something weird happened.
472
			fail("There was an unexpected error reindexing pid: " + message);
473
		}
474
	}
475

    
476
	/**
477
	 * Method to hanld login action
478
	 * 
479
	 * @param usrerName,
480
	 *            the DN name of the test method
481
	 * @param passWord,
482
	 *            the passwd of the user
483
	 */
484

    
485
	public boolean logIn(String userName, String passWord) {
486
		Properties prop = new Properties();
487
		prop.put("action", "login");
488
		prop.put("qformat", "xml");
489
		prop.put("username", userName);
490
		prop.put("password", passWord);
491

    
492
		// Now contact metacat
493
		String response = getMetacatString(prop);
494
		debug("Login Message: " + response);
495
		boolean connected = false;
496
		if (response != null && response.indexOf("<login>") != -1) {
497
			connected = true;
498
		} else {
499

    
500
			connected = false;
501
		}
502

    
503
		return connected;
504
	}
505

    
506
	/**
507
	 * Method to hanld logout action
508
	 * 
509
	 * @param usrerName,
510
	 *            the DN name of the test method
511
	 * @param passWord,
512
	 *            the passwd of the user
513
	 */
514

    
515
	public boolean handleLogOut() {
516
		boolean disConnected = false;
517
		Properties prop = new Properties();
518
		prop.put("action", "logout");
519
		prop.put("qformat", "xml");
520

    
521
		String response = getMetacatString(prop);
522
		debug("Logout Message: " + response);
523
		HttpMessage.setCookie(null);
524

    
525
		if (response.indexOf("<logout>") != -1) {
526
			disConnected = true;
527
		} else {
528
			disConnected = false;
529
		}
530

    
531
		return disConnected;
532
	}
533

    
534
	/**
535
	 * Method to hanld read both xml and data file
536
	 * 
537
	 * @param docid,
538
	 *            the docid of the document want to read
539
	 * @param qformat,
540
	 *            the format of document user want to get
541
	 */
542
	public boolean handleReadAction(String docid, String qformat) {
543
		Properties prop = new Properties();
544
		String message = "";
545
		prop.put("action", "read");
546
		prop.put("qformat", qformat);
547
		prop.put("docid", docid);
548

    
549
		message = getMetacatString(prop);
550
		message = message.trim();
551
		if (message == null || message.equals("") || message.indexOf("<error>") != -1) {// there
552
																						// was
553
																						// an
554
																						// error
555

    
556
			return false;
557
		} else {// successfully
558
			return true;
559
		}
560

    
561
	}
562

    
563
	/**
564
	 * Method to hanld inset or update xml document
565
	 * 
566
	 * @param xmlDocument,
567
	 *            the content of xml qformat
568
	 * @param docid,
569
	 *            the docid of the document
570
	 * @param action,
571
	 *            insert or update
572
	 */
573
	public boolean handleXMLDocument(String xmlDocument, String docid, String action)
574

    
575
	{ // -attempt to write file to metacat
576
		String access = "no";
577
		StringBuffer fileText = new StringBuffer();
578
		StringBuffer messageBuf = new StringBuffer();
579
		String accessFileId = null;
580
		Properties prop = new Properties();
581
		prop.put("action", action);
582
		prop.put("public", access); // This is the old way of controlling access
583
		prop.put("doctext", xmlDocument);
584
		prop.put("docid", docid);
585

    
586
		String message = getMetacatString(prop);
587
		debug("Insert or Update Message: " + message);
588
		if (message.indexOf("<error>") != -1) {// there was an error
589

    
590
			return false;
591
		} else if (message.indexOf("<success>") != -1) {// the operation worked
592
			// write the file to the cache and return the file object
593
			return true;
594

    
595
		} else {// something weird happened.
596
			return false;
597
		}
598

    
599
	}
600

    
601
	public boolean handleDeleteFile(String name) {
602

    
603
		Properties prop = new Properties();
604
		prop.put("action", "delete");
605
		prop.put("docid", name);
606

    
607
		String message = getMetacatString(prop);
608
		debug("Delete Message: " + message);
609
		if (message.indexOf("<error>") != -1) {// there was an error
610

    
611
			return false;
612
		} else if (message.indexOf("<success>") != -1) {// the operation worked
613
			// write the file to the cache and return the file object
614
			return true;
615

    
616
		} else {// something weird happened.
617
			return false;
618
		}
619
	}
620

    
621
	public String getMetacatString(Properties prop) {
622
		String response = null;
623

    
624
		// Now contact metacat and send the request
625
		try {
626
			InputStreamReader returnStream = new InputStreamReader(
627
					getMetacatInputStream(prop));
628
			StringWriter sw = new StringWriter();
629
			int len;
630
			char[] characters = new char[512];
631
			while ((len = returnStream.read(characters, 0, 512)) != -1) {
632
				sw.write(characters, 0, len);
633
			}
634
			returnStream.close();
635
			response = sw.toString();
636
			sw.close();
637
		} catch (Exception e) {
638
			return null;
639
		}
640

    
641
		return response;
642
	}
643

    
644
	/**
645
	 * Send a request to Metacat
646
	 * 
647
	 * @param prop
648
	 *            the properties to be sent to Metacat
649
	 * @return InputStream as returned by Metacat
650
	 */
651
	public InputStream getMetacatInputStream(Properties prop) {
652
		InputStream returnStream = null;
653
		// Now contact metacat and send the request
654
		try {
655

    
656
			URL url = new URL(metacatURL);
657
			HttpMessage msg = new HttpMessage(url);
658
			returnStream = msg.sendPostMessage(prop);
659
			return returnStream;
660
		} catch (Exception e) {
661
			e.printStackTrace(System.err);
662

    
663
		}
664
		return returnStream;
665

    
666
	}
667

    
668
}
(11-11/25)