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.CommandInvoker; 024 import org.crsh.text.Chunk; 025 026 import java.io.IOException; 027 028 class PipeLine implements CommandInvoker<Void, Chunk> { 029 030 /** . */ 031 private final CommandInvoker[] invokers; 032 033 /** . */ 034 private Pipe current; 035 036 PipeLine(CommandInvoker[] invokers) { 037 this.invokers = invokers; 038 this.current = null; 039 } 040 041 public Class<Void> getConsumedType() { 042 throw new UnsupportedOperationException(); 043 } 044 045 public Class<Chunk> getProducedType() { 046 throw new UnsupportedOperationException(); 047 } 048 049 public void open(CommandContext<Chunk> consumer) { 050 open(0, consumer); 051 } 052 053 private CommandContext open(final int index, final CommandContext last) { 054 if (index < invokers.length) { 055 056 // 057 final CommandInvoker invoker = invokers[index]; 058 CommandContext next = open(index + 1, last); 059 060 // 061 final Class produced = invoker.getProducedType(); 062 final Class<?> consumed = next.getConsumedType(); 063 boolean piped = index > 0; 064 if (!consumed.isAssignableFrom(produced)) { 065 if (produced.equals(Void.class) || consumed.equals(Void.class)) { 066 // We need to check (i.e test) what happens for chunk (i.e the writer) 067 PipeFilter.Sink filter = new PipeFilter.Sink(consumed, piped); 068 filter.open(next); 069 next = filter; 070 } else if (consumed.equals(Chunk.class)) { 071 PipeFilter.Chunkizer filter = new PipeFilter.Chunkizer(piped); 072 filter.open((CommandContext<Chunk>)next); 073 next = filter; 074 } else { 075 PipeFilter.Sink filter = new PipeFilter.Sink(consumed, piped); 076 filter.open(next); 077 next = filter; 078 } 079 } else { 080 PipeFilter.Noop filter = new PipeFilter.Noop(piped); 081 filter.open(next); 082 next = filter; 083 } 084 085 // 086 Pipe filterContext = new Pipe(invoker); 087 filterContext.open(next); 088 089 // Save current filter in field 090 // so if anything wrong happens it will be closed 091 current = filterContext; 092 093 // 094 return filterContext; 095 } else { 096 return last; 097 } 098 } 099 100 public void provide(Void element) throws IOException { 101 throw new UnsupportedOperationException("This is not yet implemented"); 102 } 103 104 public void flush() throws IOException { 105 current.flush(); 106 } 107 108 public void close() throws IOException { 109 current.close(); 110 } 111 }