001/**************************************************************** 002 * Licensed to the Apache Software Foundation (ASF) under one * 003 * or more contributor license agreements. See the NOTICE file * 004 * distributed with this work for additional information * 005 * regarding copyright ownership. The ASF licenses this file * 006 * to you under the Apache License, Version 2.0 (the * 007 * "License"); you may not use this file except in compliance * 008 * with the License. You may obtain a copy of the License at * 009 * * 010 * http://www.apache.org/licenses/LICENSE-2.0 * 011 * * 012 * Unless required by applicable law or agreed to in writing, * 013 * software distributed under the License is distributed on an * 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 015 * KIND, either express or implied. See the License for the * 016 * specific language governing permissions and limitations * 017 * under the License. * 018 ****************************************************************/ 019 020package org.apache.james.mpt.protocol; 021 022import java.io.BufferedReader; 023import java.io.InputStream; 024import java.io.InputStreamReader; 025import java.util.ArrayList; 026import java.util.List; 027 028import org.apache.commons.io.IOUtils; 029import org.apache.james.mpt.protocol.ProtocolSession.TimerCommand; 030 031/** 032 * A builder which generates a ProtocolSession from a test file. 033 * 034 * @author Darrell DeBoer <darrell@apache.org> 035 * 036 * @version $Revision$ 037 */ 038public class FileProtocolSessionBuilder extends ProtocolSessionBuilder { 039 040 public static final String DEBUG = "DEBUG"; 041 public static final String INFO = "INFO"; 042 public static final String WARN = "WARN"; 043 public static final String ERR = "ERR"; 044 045 private static final int TIMER_COMMAND_START = TIMER.length() + 1; 046 private static final int TIMER_COMMAND_END = TIMER_COMMAND_START + 5; 047 048 /** 049 * Builds a ProtocolSession by reading lines from the test file with the 050 * supplied name. 051 * 052 * @param fileName 053 * The name of the protocol session file. 054 * @return The ProtocolSession 055 */ 056 public ProtocolSession buildProtocolSession(String fileName) throws Exception { 057 ProtocolSession session = new ProtocolSession(); 058 addTestFile(fileName, session); 059 return session; 060 } 061 062 /** 063 * Adds all protocol elements from a test file to the ProtocolSession 064 * supplied. 065 * 066 * @param fileName 067 * The name of the protocol session file. 068 * @param session 069 * The ProtocolSession to add the elements to. 070 */ 071 public void addTestFile(String fileName, ProtocolSession session) throws Exception { 072 // Need to find local resource. 073 InputStream is = this.getClass().getResourceAsStream(fileName); 074 if (is == null) { 075 throw new Exception("Test Resource '" + fileName + "' not found."); 076 } 077 078 try { 079 addProtocolLinesFromStream(is, session, fileName); 080 } 081 finally { 082 IOUtils.closeQuietly(is); 083 } 084 } 085 086 /** 087 * Reads ProtocolElements from the supplied InputStream and adds them to the 088 * ProtocolSession. 089 * 090 * @param is 091 * The input stream containing the protocol definition. 092 * @param session 093 * The ProtocolSession to add elements to. 094 * @param fileName 095 * The name of the source file, for error messages. 096 */ 097 public void addProtocolLinesFromStream(InputStream is, ProtocolSession session, String fileName) throws Exception { 098 int sessionNumber = -1; 099 BufferedReader reader = new BufferedReader(new InputStreamReader(is)); 100 try { 101 String next; 102 int lineNumber = -1; 103 String lastClientMsg = ""; 104 while ((next = reader.readLine()) != null) { 105 String location = fileName + ":" + lineNumber; 106 if (SERVER_CONTINUATION_TAG.equals(next)) { 107 session.CONT(sessionNumber); 108 } 109 else if (next.startsWith(CLIENT_TAG)) { 110 String clientMsg = ""; 111 if (next.length() > 3) { 112 clientMsg = next.substring(3); 113 } 114 session.CL(sessionNumber, clientMsg); 115 lastClientMsg = clientMsg; 116 } 117 else if (next.startsWith(SERVER_TAG)) { 118 String serverMsg = ""; 119 if (next.length() > 3) { 120 serverMsg = next.substring(3); 121 } 122 session.SL(sessionNumber, serverMsg, location, lastClientMsg); 123 } 124 else if (next.startsWith(WAIT)) { 125 if (next.length() > 5) { 126 session.WAIT(sessionNumber, Long.valueOf(next.substring(5))); 127 } else { 128 throw new Exception("Invalid line length on WAIT instruction : " + next); 129 } 130 } 131 else if (next.startsWith(LOG)) { 132 String logInstruction = next.substring(4); 133 if (logInstruction.startsWith(DEBUG)) { 134 session.LOG(sessionNumber, ProtocolSession.LolLevel.Debug, logInstruction.substring(6)); 135 } else if (logInstruction.startsWith(INFO)) { 136 session.LOG(sessionNumber, ProtocolSession.LolLevel.Info, logInstruction.substring(5)); 137 } else if (logInstruction.startsWith(WARN)) { 138 session.LOG(sessionNumber, ProtocolSession.LolLevel.Warn, logInstruction.substring(5)); 139 } else if (logInstruction.startsWith(ERR)) { 140 session.LOG(sessionNumber, ProtocolSession.LolLevel.Err, logInstruction.substring(4)); 141 } else { 142 throw new Exception("Unrecognized log level for " + next); 143 } 144 } 145 else if (next.startsWith(REINIT)) { 146 session.REINIT(sessionNumber); 147 } 148 else if (next.startsWith(OPEN_UNORDERED_BLOCK_TAG)) { 149 List<String> unorderedLines = new ArrayList<String>(5); 150 next = reader.readLine(); 151 152 if (next == null) 153 throw new Exception("Readline doesn't contain any data, but must not be 'null' (linenumber=" 154 + lineNumber); 155 156 while (!next.startsWith(CLOSE_UNORDERED_BLOCK_TAG)) { 157 if (!next.startsWith(SERVER_TAG)) { 158 throw new Exception("Only 'S: ' lines are permitted inside a 'SUB {' block."); 159 } 160 String serverMsg = next.substring(3); 161 unorderedLines.add(serverMsg); 162 next = reader.readLine(); 163 lineNumber++; 164 165 if (next == null) 166 throw new Exception( 167 "Readline doesn't contain any data, but must not be 'null' (linenumber=" 168 + lineNumber); 169 170 } 171 172 session.SUB(sessionNumber, unorderedLines, location, lastClientMsg); 173 } 174 else if (next.startsWith(COMMENT_TAG) || next.trim().length() == 0) { 175 // ignore these lines. 176 } 177 else if (next.startsWith(SESSION_TAG)) { 178 String number = next.substring(SESSION_TAG.length()).trim(); 179 if (number.length() == 0) { 180 throw new Exception("No session number specified"); 181 } 182 sessionNumber = Integer.parseInt(number); 183 } 184 else if (next.startsWith(TIMER)) { 185 TimerCommand timerCommand = TimerCommand.from(next.substring(TIMER_COMMAND_START, TIMER_COMMAND_END)); 186 String timerName = next.substring(TIMER_COMMAND_END + 1); 187 session.TIMER(timerCommand, timerName); 188 } 189 else { 190 String prefix = next; 191 if (next.length() > 3) { 192 prefix = next.substring(0, 3); 193 } 194 throw new Exception("Invalid line prefix: " + prefix); 195 } 196 lineNumber++; 197 } 198 } 199 finally { 200 IOUtils.closeQuietly(reader); 201 } 202 } 203 204}