View Javadoc

1   /****************************************************************
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   ****************************************************************/
19  
20  package org.apache.james.mpt;
21  
22  import java.io.BufferedReader;
23  import java.io.InputStream;
24  import java.io.InputStreamReader;
25  import java.io.Reader;
26  import java.util.ArrayList;
27  import java.util.List;
28  import java.util.Properties;
29  
30  
31  /**
32   * A builder which generates scripts from textual input.
33   * 
34   * @author Darrell DeBoer <darrell@apache.org>
35   * 
36   * @version $Revision: 776401 $
37   */
38  public class ProtocolSessionBuilder {
39      
40      public static final String SERVER_CONTINUATION_TAG = "S: \\+";
41  
42      public static final String CLIENT_TAG = "C:";
43  
44      public static final String SERVER_TAG = "S:";
45  
46      public static final String OPEN_UNORDERED_BLOCK_TAG = "SUB {";
47  
48      public static final String CLOSE_UNORDERED_BLOCK_TAG = "}";
49  
50      public static final String COMMENT_TAG = "#";
51  
52      public static final String SESSION_TAG = "SESSION:";
53  
54      private final Properties variables;
55      
56      public ProtocolSessionBuilder() {
57          variables = new Properties();
58      }
59      
60      /**
61       * Sets a substitution varaible.
62       * The value of a variable will be substituted whereever
63       * ${<code>NAME</code>} is found in the input
64       * where <code>NAME</code> is the name of the variable.
65       * @param name not null
66       * @param value not null
67       */
68      public void setVariable(final String name, final String value) {
69          variables.put(name, value);
70      }
71      
72      /**
73       * Builds a ProtocolSession by reading lines from the test file with the
74       * supplied name.
75       * 
76       * @param fileName
77       *            The name of the protocol session file.
78       * @return The ProtocolSession
79       */
80      public ProtocolInteractor buildProtocolSession(String fileName)
81              throws Exception {
82          ProtocolInteractor session = new ProtocolSession();
83          addTestFile(fileName, session);
84          return session;
85      }
86      
87      /**
88       * Builds a ProtocolSession by reading lines from the reader.
89       * 
90       * @param scriptName not null
91       * @param reader not null
92       * @return The ProtocolSession
93       */
94      public ProtocolInteractor buildProtocolSession(final String scriptName, final Reader reader)
95              throws Exception {
96          ProtocolInteractor session = new ProtocolSession();
97          addProtocolLines(scriptName, reader, session);
98          return session;
99      }
100 
101 
102     /**
103      * Adds all protocol elements from a test file to the ProtocolSession
104      * supplied.
105      * 
106      * @param fileName
107      *            The name of the protocol session file.
108      * @param session
109      *            The ProtocolSession to add the elements to.
110      */
111     public void addTestFile(String fileName, ProtocolInteractor session)
112             throws Exception {
113         // Need to find local resource.
114         InputStream is = this.getClass().getResourceAsStream(fileName);
115         if (is == null) {
116             throw new Exception("Test Resource '" + fileName + "' not found.");
117         }
118 
119         addProtocolLines(fileName, is, session);
120     }
121 
122     /**
123      * Reads ProtocolElements from the supplied InputStream and adds them to the
124      * ProtocolSession.
125      * @param scriptName
126      *            The name of the source file, for error messages.
127      * @param is
128      *            The input stream containing the protocol definition.
129      * @param session
130      *            The ProtocolSession to add elements to.
131      */
132     public void addProtocolLines(String scriptName, InputStream is, ProtocolInteractor session) throws Exception {
133         BufferedReader reader = new BufferedReader(new InputStreamReader(is));
134         
135         doAddProtocolLines(session, scriptName, reader);
136     }
137 
138     /**
139      * Reads ProtocolElements from the supplied Reader and adds them to the
140      * ProtocolSession.
141      * @param scriptName
142      *            The name of the source file, for error messages.
143      * @param reader
144      *            the reader containing the protocol definition.
145      * @param session
146      *            The ProtocolSession to add elements to.
147      */
148     public void addProtocolLines(String scriptName, Reader reader, ProtocolInteractor session) throws Exception {
149         final BufferedReader bufferedReader;
150         if (reader instanceof BufferedReader) {
151             bufferedReader = (BufferedReader) reader;
152         } else {
153             bufferedReader = new BufferedReader(reader);
154         }
155         doAddProtocolLines(session, scriptName, bufferedReader);
156     }
157     
158     /**
159      * Reads ProtocolElements from the supplied Reader and adds them to the
160      * ProtocolSession.
161      * 
162      * @param reader
163      *            the reader containing the protocol definition.
164      * @param session
165      *            The ProtocolSession to add elements to.
166      * @param scriptName
167      *            The name of the source file, for error messages.
168      */
169     private void doAddProtocolLines(ProtocolInteractor session, String scriptName, BufferedReader reader) throws Exception {
170         String line;
171         int sessionNumber = -1;
172         int lineNumber = -1;
173         String lastClientMsg = "";
174         while ((line = reader.readLine()) != null) {
175             line = substituteVariables(line);
176             String location = scriptName + ":" + lineNumber;
177             if (SERVER_CONTINUATION_TAG.equals(line)) {
178                 session.CONT(sessionNumber);
179             } else if (line.startsWith(CLIENT_TAG)) {
180                 String clientMsg = "";
181                 if (line.length() > 3) {
182                     clientMsg = line.substring(3);
183                 }
184                 session.CL(sessionNumber, clientMsg);
185                 lastClientMsg = clientMsg;
186             } else if (line.startsWith(SERVER_TAG)) {
187                 String serverMsg = "";
188                 if (line.length() > 3) {
189                     serverMsg = line.substring(3);
190                 }
191                 session.SL(sessionNumber, serverMsg, location, lastClientMsg);
192             } else if (line.startsWith(OPEN_UNORDERED_BLOCK_TAG)) {
193                 List<String> unorderedLines = new ArrayList<String>(5);
194                 line = reader.readLine();
195 
196                 while (!line.startsWith(CLOSE_UNORDERED_BLOCK_TAG)) {
197                     if (!line.startsWith(SERVER_TAG)) {
198                         throw new Exception(
199                                 "Only 'S: ' lines are permitted inside a 'SUB {' block.");
200                     }
201                     String serverMsg = line.substring(3);
202                     unorderedLines.add(serverMsg);
203                     line = reader.readLine();
204                     lineNumber++;
205                 }
206 
207                 session.SUB(sessionNumber, unorderedLines, location,
208                         lastClientMsg);
209             } else if (line.startsWith(COMMENT_TAG)
210                     || line.trim().length() == 0) {
211                 // ignore these lines.
212             } else if (line.startsWith(SESSION_TAG)) {
213                 String number = line.substring(SESSION_TAG.length()).trim();
214                 if (number.length() == 0) {
215                     throw new Exception("No session number specified");
216                 }
217                 sessionNumber = Integer.parseInt(number);
218             } else {
219                 String prefix = line;
220                 if (line.length() > 3) {
221                     prefix = line.substring(0, 3);
222                 }
223                 throw new Exception("Invalid line prefix: " + prefix);
224             }
225             lineNumber++;
226         }
227     }
228 
229     /**
230      * Replaces ${<code>NAME</code>} with variable value.
231      * @param line not null
232      * @return not null
233      */
234     private String substituteVariables(String line) {
235         if (variables.size() > 0) {
236             final StringBuffer buffer = new StringBuffer(line);
237             int start = 0;
238             int end = 0;
239             while (start >= 0 && end >= 0) { 
240                 start = buffer.indexOf("${", end);
241                 if (start < 0) {
242                     break;
243                 }
244                 end = buffer.indexOf("}", start);
245                 if (end < 0) {
246                     break;
247                 }
248                 final String name = buffer.substring(start+2, end);
249                 final String value = variables.getProperty(name);
250                 if (value != null) {
251                     buffer.replace(start, end + 1, value);
252                     final int variableLength = (end - start + 2);
253                     end = end + (value.length() - variableLength);
254                 }
255             }
256             line = buffer.toString();
257         }
258         return line;
259     }
260 
261 }