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.lang.script; 021 022import org.crsh.shell.impl.command.spi.CommandCreationException; 023import org.crsh.shell.impl.command.spi.CommandInvoker; 024import org.crsh.shell.impl.command.spi.ShellCommand; 025import org.crsh.command.SyntaxException; 026import org.crsh.repl.ReplSession; 027import org.crsh.shell.impl.command.pipeline.PipeLine; 028import org.crsh.shell.ErrorType; 029import org.crsh.text.Chunk; 030 031import java.util.LinkedList; 032import java.util.regex.Pattern; 033 034/** 035 * A factory for a pipeline. 036 */ 037public class PipeLineFactory { 038 039 /** . */ 040 private static final Pattern p = Pattern.compile("^\\s*(\\S+)"); 041 042 /** . */ 043 final String line; 044 045 /** . */ 046 final String name; 047 048 /** . */ 049 final String rest; 050 051 /** . */ 052 final PipeLineFactory next; 053 054 /** 055 * Create a pipeline factory for the specified line and next factory 056 * 057 * @param line the line 058 * @param next the next factory 059 * @throws SyntaxException when the line is not correct 060 */ 061 public PipeLineFactory(String line, PipeLineFactory next) throws SyntaxException { 062 java.util.regex.Matcher m = p.matcher(line); 063 if (m.find()) { 064 this.name = m.group(1); 065 this.rest = line.substring(m.end()); 066 this.line = line; 067 this.next = next; 068 } else { 069 StringBuilder sb = new StringBuilder("syntax error near unexpected token"); 070 if (next != null) { 071 sb.append(' '); 072 for (PipeLineFactory factory = next;factory != null;factory = factory.next) { 073 sb.append('|').append(factory.line); 074 } 075 } 076 throw new SyntaxException(sb.toString()); 077 } 078 } 079 080 public String getLine() { 081 return line; 082 } 083 084 public PipeLineFactory getNext() { 085 return next; 086 } 087 088 public CommandInvoker<Void, Chunk> create(ReplSession session) throws CommandCreationException { 089 LinkedList<CommandInvoker> pipes = new LinkedList<CommandInvoker>(); 090 for (PipeLineFactory current = this;current != null;current = current.next) { 091 ShellCommand<?> command = session.getCommand(current.name); 092 if (command == null) { 093 throw new CommandCreationException(current.name, ErrorType.EVALUATION, "Unknown command"); 094 } 095 CommandInvoker commandInvoker = command.resolveInvoker(current.rest); 096 if (commandInvoker == null) { 097 throw new CommandCreationException(current.name, ErrorType.EVALUATION, "Command " + current.rest + " cannot not be invoked"); 098 } 099 pipes.add(commandInvoker); 100 } 101 return new PipeLine(pipes.toArray(new CommandInvoker[pipes.size()])); 102 } 103 104 public PipeLineFactory getLast() { 105 if (next != null) { 106 return next.getLast(); 107 } 108 return this; 109 } 110}