001: /*
002: * The contents of this file are subject to the terms of the
003: * Common Development and Distribution License, Version 1.0 only
004: * (the "License"). You may not use this file except in compliance
005: * with the License. A copy of the license is available
006: * at http://www.opensource.org/licenses/cddl1.php
007: *
008: * See the License for the specific language governing permissions
009: * and limitations under the License.
010: *
011: * The Original Code is the dvbcentral.sf.net project.
012: * The Initial Developer of the Original Code is Jaroslav Tulach.
013: * Portions created by Jaroslav Tulach are Copyright (C) 2006.
014: * All Rights Reserved.
015:
016: If you wish your version of this file to be governed by only the CDDL
017: or only the GPL Version 2, indicate your decision by adding
018: "[Contributor] elects to include this software in this distribution
019: under the [CDDL or GPL Version 2] license." If you do not indicate a
020: single choice of license, a recipient has the option to distribute
021: your version of this file under either the CDDL, the GPL Version 2 or
022: to extend the choice of license to its licensees as provided above.
023: However, if you add GPL Version 2 code and therefore, elected the GPL
024: Version 2 license, then the option applies only if the new code is
025: made subject to such option by the copyright holder.
026: */
027: package org.netbeans.api.sendopts;
028:
029: import java.io.ByteArrayOutputStream;
030: import java.io.File;
031: import java.io.IOException;
032: import java.io.OutputStream;
033: import java.io.PrintStream;
034: import java.nio.ByteBuffer;
035: import java.nio.channels.WritableByteChannel;
036: import java.util.ArrayList;
037: import java.util.Collections;
038: import java.util.List;
039: import java.util.Map;
040: import java.util.Set;
041: import org.netbeans.spi.sendopts.OptionGroups;
042: import org.netbeans.spi.sendopts.Env;
043: import org.netbeans.spi.sendopts.Option;
044: import org.netbeans.spi.sendopts.OptionProcessor;
045: import org.openide.util.Lookup;
046: import org.openide.util.lookup.AbstractLookup;
047: import org.openide.util.lookup.InstanceContent;
048:
049: /**
050: *
051: * @author Jaroslav Tulach
052: */
053: public class StreamingTest extends junit.framework.TestCase {
054: static {
055: System.setProperty("org.openide.util.Lookup", Lkp.class
056: .getName());
057: }
058:
059: /** content to things to lookup to */
060: private InstanceContent ic;
061:
062: private File tmpDir;
063:
064: public StreamingTest(String testName) {
065: super (testName);
066: }
067:
068: protected void setUp() throws Exception {
069: File f = File.createTempFile(getName(), "tmp");
070: f.delete();
071: f.mkdirs();
072: assertTrue("We created a directory", f.isDirectory());
073:
074: File[] arr = f.listFiles();
075: for (int i = 0; i < arr.length; i++) {
076: arr[i].delete();
077: }
078: tmpDir = f;
079:
080: Lookup l = Lookup.getDefault();
081: assertEquals(Lkp.class, l.getClass());
082: Lkp lkp = (Lkp) l;
083:
084: this .ic = lkp.ic;
085: // clear the lookup
086: lkp.ic.set(Collections.emptyList(), null);
087: lkp.ic.add(new P());
088: }
089:
090: protected void tearDown() throws Exception {
091: Lookup l = Lookup.getDefault();
092: assertEquals(Lkp.class, l.getClass());
093: Lkp lkp = (Lkp) l;
094: // clear the lookup
095: lkp.ic.set(Collections.emptyList(), null);
096: }
097:
098: public void testWeCanRegisterIOStream() throws Exception {
099: StreamSinkProvider ssp = new StreamSinkProvider();
100: ic.add(ssp);
101:
102: ByteArrayOutputStream osInner = new ByteArrayOutputStream();
103: PrintStream os = new PrintStream(osInner);
104: CommandLine.getDefault().process(new String[] { "--stream" },
105: null, os, null, tmpDir);
106:
107: assertNotNull("A sink was really created", ssp.created);
108: ssp.created.close();
109: assertEquals("Closed with right data", os, ssp.created.data);
110: }
111:
112: public void testWeCanRegisterTwoSinks() throws Exception {
113: StreamSinkProvider ssp = new StreamSinkProvider();
114: ic.add(ssp);
115: FileSinkProvider fsp = new FileSinkProvider();
116: ic.add(fsp);
117:
118: CommandLine.getDefault().process(
119: new String[] { "--file", "Ahoj.mpeg" }, null, null,
120: null, tmpDir);
121:
122: assertNull("No stream", ssp.created);
123: assertNotNull("A file sink was created", fsp.created);
124: fsp.created.close();
125: assertEquals("Closed with right data", new File(tmpDir,
126: "Ahoj.mpeg"), fsp.created.data);
127:
128: }
129:
130: public static abstract class SinkProvider {
131: /** associated option */
132: final Option option;
133:
134: /** Constructor for subclasses to register their own {@link Sink}.
135: * The option shall describe the content of command line that is necessary
136: * for construction of the {@link Sink}.
137: *
138: * @param option the option representing the command line part needed for
139: * construction of the {@link Sink}
140: */
141: protected SinkProvider(Option option) {
142: this .option = option;
143: }
144:
145: /** Returns an option that can be used to construct a "sink". The
146: * option is required to parse the command line and process them
147: * into an implementation of a "sink". The sink is then going to be
148: * fed with read data.
149: *
150: * @return the sink
151: */
152: protected abstract Sink createSink(Env env,
153: Map<Option, String[]> values) throws CommandException;
154: }
155:
156: public static abstract class Sink {
157: public static Sink create(String n, WritableByteChannel b,
158: boolean x) {
159: return null;
160: }
161: }
162:
163: private class StreamSinkProvider extends SinkProvider {
164: WBC created;
165:
166: public StreamSinkProvider() {
167: super (Option
168: .withoutArgument(Option.NO_SHORT_NAME, "stream"));
169: }
170:
171: protected Sink createSink(Env env, Map<Option, String[]> values)
172: throws CommandException {
173: created = new WBC(env.getOutputStream());
174: return Sink.create("no name", created, true);
175: }
176:
177: private class WBC implements WritableByteChannel {
178: private OutputStream data;
179:
180: public WBC(OutputStream d) {
181: this .data = d;
182: }
183:
184: public void close() throws IOException {
185: assertNotNull("Some data", this .data);
186: }
187:
188: public int write(ByteBuffer src) throws IOException {
189: return src.remaining();
190: }
191:
192: public boolean isOpen() {
193: return true;
194: }
195: }
196: }
197:
198: private static Option file = Option.requiredArgument(
199: Option.NO_SHORT_NAME, "file");
200:
201: private class FileSinkProvider extends SinkProvider {
202: WBC created;
203:
204: protected FileSinkProvider() {
205: super (file);
206: }
207:
208: protected Sink createSink(Env env, Map<Option, String[]> values)
209: throws CommandException {
210: File f = new File(env.getCurrentDirectory(), values
211: .get(file)[0]);
212: created = new WBC(f);
213: return Sink.create("some file", created, true);
214: }
215:
216: private class WBC implements WritableByteChannel {
217: private File data;
218:
219: public WBC(File d) {
220: this .data = d;
221: }
222:
223: public void close() throws IOException {
224: assertNotNull("Some data", this .data);
225: }
226:
227: public int write(ByteBuffer src) throws IOException {
228: return src.remaining();
229: }
230:
231: public boolean isOpen() {
232: return true;
233: }
234: }
235: }
236:
237: public static final class Lkp extends AbstractLookup {
238: public InstanceContent ic;
239:
240: public Lkp() {
241: this (new InstanceContent());
242: }
243:
244: private Lkp(InstanceContent ic) {
245: super (ic);
246: this .ic = ic;
247: }
248:
249: }
250:
251: public static final class P extends OptionProcessor {
252: public P() {
253: }
254:
255: private final List<Option> all() {
256: List<Option> list = new ArrayList<Option>();
257: for (SinkProvider sp : Lookup.getDefault().lookupAll(
258: SinkProvider.class)) {
259: list.add(sp.option);
260: }
261: return list;
262: }
263:
264: protected Set<Option> getOptions() {
265: Option o = OptionGroups.oneOf(all().toArray(new Option[0]));
266: return Collections.singleton(o);
267: }
268:
269: protected void process(Env env, Map<Option, String[]> values)
270: throws CommandException {
271: boolean was = false;
272: for (SinkProvider sp : Lookup.getDefault().lookupAll(
273: SinkProvider.class)) {
274: if (values.containsKey(sp.option)) {
275: assertFalse("Not called yet", was);
276: sp.createSink(env, values);
277: was = true;
278: }
279: }
280: }
281: }
282: }
|