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 package org.crsh.lang.impl.java; 020 021 import org.crsh.cli.impl.invocation.CommandInvoker; 022 import org.crsh.cli.impl.invocation.InvocationException; 023 import org.crsh.cli.impl.lang.Instance; 024 import org.crsh.command.BaseCommand; 025 import org.crsh.command.CommandContext; 026 import org.crsh.command.InvocationContext; 027 import org.crsh.keyboard.KeyHandler; 028 import org.crsh.shell.ErrorKind; 029 import org.crsh.shell.impl.command.InvocationContextImpl; 030 import org.crsh.shell.impl.command.spi.CommandException; 031 032 import java.io.IOException; 033 034 /** 035 * @author Julien Viet 036 */ 037 class ProducerCommandMatch<T extends BaseCommand, P> extends BaseCommandMatch<T, Void, P> { 038 039 /** . */ 040 private final CommandInvoker<Instance<T>, ?> invoker; 041 042 /** . */ 043 private final Class<P> producedType; 044 045 /** . */ 046 private final String name; 047 048 public ProducerCommandMatch(ClassShellCommand<T> shellCommand, CommandInvoker<Instance<T>, ?> invoker, Class<P> producedType) { 049 super(shellCommand); 050 051 // 052 this.invoker = invoker; 053 this.producedType = producedType; 054 this.name = shellCommand.getDescriptor().getName(); 055 } 056 057 @Override 058 public Class<P> getProducedType() { 059 return producedType; 060 } 061 062 @Override 063 public Class<Void> getConsumedType() { 064 return Void.class; 065 } 066 067 @Override 068 BaseInvoker getInvoker(T command) throws CommandException { 069 070 // 071 return new BaseInvoker(command) { 072 073 /** . */ 074 private InvocationContext<P> invocationContext; 075 076 public Class<P> getProducedType() { 077 return producedType; 078 } 079 080 public Class<Void> getConsumedType() { 081 return Void.class; 082 } 083 084 public void open(CommandContext<? super P> consumer) { 085 // Java is fine with that but not intellij.... 086 CommandContext<P> consumer2 = (CommandContext<P>)consumer; 087 open2(consumer2); 088 } 089 090 public void open2(final CommandContext<P> consumer) { 091 invocationContext = new InvocationContextImpl<P>(consumer); 092 command.pushContext(invocationContext); 093 command.unmatched = invoker.getMatch().getRest(); 094 } 095 096 097 @Override 098 public KeyHandler getKeyHandler() { 099 if (command instanceof KeyHandler) { 100 return (KeyHandler)command; 101 } else { 102 return null; 103 } 104 } 105 106 public void provide(Void element) { 107 // Drop everything 108 } 109 110 public void flush() { 111 } 112 113 public void close() throws IOException, CommandException { 114 try { 115 Object ret; 116 try { 117 ret = invoker.invoke(this); 118 } 119 catch (org.crsh.cli.impl.SyntaxException e) { 120 throw new CommandException(ErrorKind.SYNTAX, "Syntax exception when executing command " + name, e); 121 } catch (InvocationException e) { 122 throw new CommandException(ErrorKind.EVALUATION, "Command " + name + " failed", e.getCause()); 123 } 124 125 // Anything returned compatible is then produced 126 if (ret != null && producedType.isInstance(ret)) { 127 P produced = producedType.cast(ret); 128 try { 129 invocationContext.provide(produced); 130 } 131 catch (Exception e) { 132 throw new CommandException(ErrorKind.EVALUATION, "Command " + name + " failed", e); 133 } 134 } 135 } finally { 136 try { 137 invocationContext.flush(); 138 } 139 finally { 140 try { 141 invocationContext.close(); 142 } 143 catch (Exception e) { 144 throw new CommandException(ErrorKind.EVALUATION, "Command " + name + " failed", e); 145 } finally { 146 command.unmatched = null; 147 invocationContext = null; 148 } 149 } 150 } 151 } 152 }; 153 } 154 }