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