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 020package org.crsh.command.pipeline; 021 022import org.crsh.command.CommandContext; 023import org.crsh.command.CommandInvoker; 024import org.crsh.text.Chunk; 025 026import java.io.IOException; 027 028public class PipeLine extends CommandInvoker<Void, Chunk> { 029 030 /** . */ 031 private final CommandInvoker[] invokers; 032 033 /** . */ 034 private CommandContext<?> current; 035 036 public PipeLine(CommandInvoker[] invokers) { 037 this.invokers = invokers; 038 this.current = null; 039 } 040 041 public Class<Void> getConsumedType() { 042 return Void.class; 043 } 044 045 public Class<Chunk> getProducedType() { 046 return Chunk.class; 047 } 048 049 public void open(CommandContext<? super 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 065 AbstractPipe filter; 066 if (consumed.equals(Chunk.class)) { 067 filter = new ToChunkPipe(produced, piped); 068 } else { 069 filter = new ConvertingPipe(produced, consumed, piped); 070 } 071 filter.open(next); 072 next = filter; 073 074 // 075 PipeLineElement filterContext = new PipeLineElement(invoker); 076 filterContext.open(next); 077 078 // Save current filter in field 079 // so if anything wrong happens it will be closed 080 current = filterContext; 081 082 // 083 return filterContext; 084 } else { 085 current = last; 086 return last; 087 } 088 } 089 090 public void provide(Void element) throws IOException { 091 // Ignore 092 } 093 094 public void flush() throws IOException { 095 current.flush(); 096 } 097 098 public void close() throws IOException { 099 current.close(); 100 } 101}