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 */ 019package org.crsh.lang.java; 020 021import org.crsh.cli.impl.invocation.CommandInvoker; 022import org.crsh.cli.impl.invocation.InvocationException; 023import org.crsh.cli.impl.invocation.InvocationMatch; 024import org.crsh.cli.impl.lang.Instance; 025import org.crsh.command.BaseCommand; 026import org.crsh.command.CommandContext; 027import org.crsh.command.InvocationContext; 028import org.crsh.command.Pipe; 029import org.crsh.command.SyntaxException; 030import org.crsh.console.KeyHandler; 031import org.crsh.shell.impl.command.InvocationContextImpl; 032import org.crsh.shell.impl.command.spi.CommandCreationException; 033import org.crsh.util.Utils; 034 035import java.io.IOException; 036import java.lang.reflect.Type; 037 038/** 039* @author Julien Viet 040*/ 041class PipeCommandImpl<T extends BaseCommand, C, P, PC extends Pipe<C, P>> extends CommandImpl<T, C, P> { 042 043 /** . */ 044 final Type ret; 045 046 /** . */ 047 final Class<C> consumedType; 048 049 /** . */ 050 final Class<P> producedType; 051 private final CommandInvoker<Instance<T>, PC> invoker; 052 053 public PipeCommandImpl(ShellCommandImpl<T> baseShellCommand, CommandInvoker<Instance<T>, PC> invoker) { 054 super(baseShellCommand); 055 this.invoker = invoker; 056 ret = invoker.getGenericReturnType(); 057 consumedType = (Class<C>)Utils.resolveToClass(ret, Pipe.class, 0); 058 producedType = (Class<P>)Utils.resolveToClass(ret, Pipe.class, 1); 059 } 060 061 @Override 062 public InvocationMatch<?> getMatch() { 063 return invoker.getMatch(); 064 } 065 066 @Override 067 public Class<P> getProducedType() { 068 return producedType; 069 } 070 071 @Override 072 public Class<C> getConsumedType() { 073 return consumedType; 074 } 075 076 @Override 077 BaseInvoker getInvoker(T command) throws CommandCreationException { 078 079 // 080 return new BaseInvoker(command) { 081 082 Pipe<C, P> real; 083 InvocationContext<P> invocationContext; 084 085 public Class<P> getProducedType() { 086 return producedType; 087 } 088 089 public Class<C> getConsumedType() { 090 return consumedType; 091 } 092 093 public void open(CommandContext<? super P> consumer) { 094 // Java is fine with that but not intellij.... 095 CommandContext<P> consumer2 = (CommandContext<P>)consumer; 096 open2(consumer2); 097 } 098 099 @Override 100 public KeyHandler getKeyHandler() { 101 return command instanceof KeyHandler ? (KeyHandler)command : null; 102 } 103 104 public void open2(final CommandContext<P> consumer) { 105 106 // 107 invocationContext = new InvocationContextImpl<P>(consumer); 108 109 // Push context 110 command.pushContext(invocationContext); 111 112 // Set the unmatched part 113 command.unmatched = invoker.getMatch().getRest(); 114 115 // 116 PC ret; 117 try { 118 ret = invoker.invoke(this); 119 } 120 catch (org.crsh.cli.SyntaxException e) { 121 throw new SyntaxException(e.getMessage()); 122 } catch (InvocationException e) { 123 throw command.toScript(e.getCause()); 124 } 125 126 // It's a pipe command 127 if (ret != null) { 128 real = ret; 129 real.open(invocationContext); 130 } 131 } 132 133 public void provide(C element) throws IOException { 134 if (real != null) { 135 real.provide(element); 136 } 137 } 138 139 public void flush() throws IOException { 140 if (real != null) { 141 real.flush(); 142 } else { 143 invocationContext.flush(); 144 } 145 } 146 147 public void close() throws IOException { 148 try { 149 if (real != null) { 150 try { 151 real.close(); 152 } 153 finally { 154 Utils.close(invocationContext); 155 } 156 } else { 157 Utils.close(invocationContext); 158 } 159 } 160 finally { 161 command.popContext(); 162 command.unmatched = null; 163 } 164 } 165 }; 166 } 167}