001 /*
002 * Copyright (C) 2012 eXo Platform SAS.
003 *
004 * This is free software; you can redistribute it and/or modify it
005 * under the terms of the GNU Lesser General Public License as
006 * published by the Free Software Foundation; either version 2.1 of
007 * the License, or (at your option) any later version.
008 *
009 * This software is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * You should have received a copy of the GNU Lesser General Public
015 * License along with this software; if not, write to the Free
016 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
017 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
018 */
019
020 package org.crsh.shell.impl.command;
021
022 import org.crsh.command.CommandContext;
023 import org.crsh.command.ScriptException;
024 import org.crsh.shell.InteractionContext;
025 import org.crsh.io.Filter;
026 import org.crsh.shell.ScreenContext;
027 import org.crsh.text.Chunk;
028 import org.crsh.text.ChunkAdapter;
029
030 import java.io.IOException;
031 import java.util.Map;
032
033 /** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
034 abstract class Pipe<C, P> implements Filter<C, P, CommandContext<P>>, CommandContext<C> {
035
036 /** . */
037 protected CommandContext<P> context;
038
039 public final boolean takeAlternateBuffer() throws IOException {
040 return context.takeAlternateBuffer();
041 }
042
043 public final boolean releaseAlternateBuffer() throws IOException {
044 return context.releaseAlternateBuffer();
045 }
046
047 public final String getProperty(String propertyName) {
048 return context.getProperty(propertyName);
049 }
050
051 public final String readLine(String msg, boolean echo) {
052 return context.readLine(msg, echo);
053 }
054
055 public final int getWidth() {
056 return context.getWidth();
057 }
058
059 public final int getHeight() {
060 return context.getHeight();
061 }
062
063 public Map<String, Object> getSession() {
064 return context.getSession();
065 }
066
067 public Map<String, Object> getAttributes() {
068 return context.getAttributes();
069 }
070
071 /**
072 * A pipe filter that invokes a command through a {@link org.crsh.command.CommandInvoker}.
073 */
074 static class Invoker<C, P> extends Pipe<C, P> {
075
076 /** . */
077 final Filter<C, P, InteractionContext<P>> command;
078
079 Invoker(Filter<C, P, InteractionContext<P>> command) {
080 this.command = command;
081 }
082
083 public void setPiped(boolean piped) {
084 command.setPiped(piped);
085 }
086
087 public Class<P> getProducedType() {
088 return command.getProducedType();
089 }
090
091 public Class<C> getConsumedType() {
092 return command.getConsumedType();
093 }
094
095 public void open(CommandContext<P> consumer) {
096 this.context = consumer;
097 this.command.open(consumer);
098 }
099
100 public void provide(C element) throws IOException {
101 if (command.getConsumedType().isInstance(element)) {
102 command.provide(element);
103 }
104 }
105
106 public void flush() throws IOException {
107 command.flush();
108 }
109
110 public void close() throws ScriptException {
111 command.close();
112 }
113 }
114
115 static class Chunkizer extends Pipe<Object, Chunk> {
116
117 /** . */
118 private ChunkAdapter ca;
119
120 public Class<Chunk> getProducedType() {
121 return Chunk.class;
122 }
123
124 public Class<Object> getConsumedType() {
125 return Object.class;
126 }
127
128 public void setPiped(boolean piped) {
129 ((Pipe<Chunk, ?>)context).setPiped(piped);
130 }
131
132 public void open(final CommandContext<Chunk> consumer) {
133 ca = new ChunkAdapter(new ScreenContext<Chunk>() {
134 public int getWidth() {
135 return consumer.getWidth();
136 }
137 public int getHeight() {
138 return consumer.getHeight();
139 }
140 public Class<Chunk> getConsumedType() {
141 return Chunk.class;
142 }
143 public void provide(Chunk element) throws IOException {
144 Chunkizer.this.context.provide(element);
145 }
146 public void flush() throws IOException {
147 Chunkizer.this.context.flush();
148 }
149 });
150
151 this.context = consumer;
152 }
153
154 public void provide(Object element) throws ScriptException, IOException {
155 ca.provide(element);
156 }
157
158 public void flush() throws ScriptException, IOException {
159 ca.flush();
160 }
161
162 public void close() throws ScriptException {
163 ((Pipe<Chunk, ?>)context).close();
164 }
165 }
166
167 static class Sink<P> extends Pipe<Object, P> {
168
169 /** . */
170 private final Class<P> producedType;
171
172 Sink(Class<P> producedType) {
173 this.producedType = producedType;
174 }
175
176 public Class<P> getProducedType() {
177 return producedType;
178 }
179
180 public void setPiped(boolean piped) {
181 }
182
183 public void open(CommandContext<P> consumer) {
184 this.context = consumer;
185 }
186
187 public void provide(Object element) throws IOException {
188 }
189
190 public Class<Object> getConsumedType() {
191 return Object.class;
192 }
193
194 public void flush() throws IOException {
195 context.flush();
196 }
197
198 public void close() {
199 ((Pipe<P, ?>)context).close();
200 }
201 }
202 }