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.mina.example.tapedeck;
21  
22  import static org.apache.mina.statemachine.event.IoFilterEvents.*;
23  
24  import org.apache.mina.core.filterchain.IoFilter.NextFilter;
25  import org.apache.mina.core.future.IoFutureListener;
26  import org.apache.mina.core.session.IoSession;
27  import org.apache.mina.core.write.WriteRequest;
28  import org.apache.mina.example.tapedeck.TapeDeckServer.TapeDeckContext;
29  import org.apache.mina.statemachine.StateControl;
30  import org.apache.mina.statemachine.annotation.IoFilterTransition;
31  import org.apache.mina.statemachine.annotation.State;
32  import org.apache.mina.statemachine.context.AbstractStateContext;
33  
34  /**
35   * TODO Add documentation
36   * 
37   * @author The Apache MINA Project (dev@mina.apache.org)
38   * @version $Rev: 600461 $, $Date: 2007-12-03 10:55:52 +0100 (Mon, 03 Dec 2007) $
39   */
40  public class AuthenticationHandler {
41      @State public static final String ROOT = "Root";
42      @State(ROOT) public static final String START = "Start";
43      @State(ROOT) public static final String WAIT_USER = "WaitUser";
44      @State(ROOT) public static final String WAIT_PASSWORD = "WaitPassword";
45      @State(ROOT) public static final String DONE = "Done";
46      @State(ROOT) public static final String FAILED = "Failed";
47  
48      static class AuthenticationContext extends AbstractStateContext {
49          public String user;
50          public String password;
51          public int tries = 0;
52      }
53  
54      @IoFilterTransition(on = SESSION_OPENED, in = START, next = WAIT_USER)
55      public void sendAuthRequest(NextFilter nextFilter, IoSession session) {
56          session.write("+ Greetings from your tape deck!. Please authenticate yourself.");
57      }
58      
59      @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_USER, next = WAIT_PASSWORD)
60      public void user(AuthenticationContext context, NextFilter nextFilter, IoSession session, UserCommand cmd) {
61          context.user = cmd.getUsername();
62          session.write("+ Give me your password (hint: try your username backwards)");
63      }
64      
65      @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_PASSWORD, next = DONE)
66      public void password(AuthenticationContext context, NextFilter nextFilter, IoSession session, PasswordCommand cmd) {
67          context.password = cmd.getPassword();
68          if (context.password.equals(reverse(context.user))) {
69              session.write("+ Authentication succeeded! Your tape deck has been unlocked.");
70          } else {
71              context.tries++;
72              if (context.tries < 3) {
73                  session.write("- Authentication failed! Please try again.");
74                  StateControl.breakAndGotoNext(WAIT_USER);
75              } else {
76                  session.write("- Authentication failed too many times! Bye bye.").addListener(IoFutureListener.CLOSE);
77                  StateControl.breakAndGotoNext(FAILED);
78              }
79          }
80      }
81      
82      
83      @IoFilterTransition(on = MESSAGE_RECEIVED, in = ROOT)
84      public void quit(TapeDeckContext context, IoSession session, QuitCommand cmd) {
85          session.write("+ Bye! Please come back!").addListener(IoFutureListener.CLOSE);
86      }
87      
88      private String reverse(String s) {
89          char[] expectedPassword = new char[s.length()];
90          for (int i = 0; i < expectedPassword.length; i++) {
91              expectedPassword[i] = s.charAt(s.length() - i - 1);
92          }
93          return new String(expectedPassword);
94      }
95      
96      @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_USER, weight = 10)
97      public void errorWaitingForUser(IoSession session, Command cmd) {
98          if (cmd instanceof QuitCommand) {
99              StateControl.breakAndContinue();
100         }
101         session.write("Unexpected command '" + cmd.getName() + "'. Expected 'user <username>'.");
102     }
103     
104     @IoFilterTransition(on = MESSAGE_RECEIVED, in = WAIT_PASSWORD, weight = 10)
105     public void errorWaitingForPassword(IoSession session, Command cmd) {
106         if (cmd instanceof QuitCommand) {
107             StateControl.breakAndContinue();
108         }
109         session.write("Unexpected command '" + cmd.getName() + "'. Expected 'password <password>'.");
110     }
111     
112     @IoFilterTransition(on = EXCEPTION_CAUGHT, in = ROOT)
113     public void commandSyntaxError(IoSession session, CommandSyntaxException e) {
114         session.write("- " + e.getMessage());
115     }
116     
117     @IoFilterTransition(on = EXCEPTION_CAUGHT, in = ROOT, weight = 10)
118     public void exceptionCaught(IoSession session, Exception e) {
119         e.printStackTrace();
120         session.close();
121     }
122     
123 //    
124 //    @IoFilterTransition(on = SESSION_CREATED, in = ROOT)
125 //    public void sessionCreated(NextFilter nextFilter, IoSession session) {
126 //        nextFilter.sessionCreated(session);
127 //    }
128 //    @IoFilterTransition(on = SESSION_OPENED, in = ROOT)
129 //    public void sessionOpened(NextFilter nextFilter, IoSession session) {
130 //        nextFilter.sessionOpened(session);
131 //    }
132     
133     @IoFilterTransition(on = SESSION_CLOSED, in = DONE)
134     public void sessionClosed(NextFilter nextFilter, IoSession session) {
135         nextFilter.sessionClosed(session);
136     }
137     @IoFilterTransition(on = EXCEPTION_CAUGHT, in = DONE)
138     public void exceptionCaught(NextFilter nextFilter, IoSession session, Throwable cause) {
139         nextFilter.exceptionCaught(session, cause);
140     }
141     @IoFilterTransition(on = MESSAGE_RECEIVED, in = DONE)
142     public void messageReceived(NextFilter nextFilter, IoSession session, Object message) {
143         nextFilter.messageReceived(session, message);
144     }
145     @IoFilterTransition(on = MESSAGE_SENT, in = DONE)
146     public void messageSent(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) {
147         nextFilter.messageSent(session, writeRequest);
148     }
149     
150     @IoFilterTransition(on = CLOSE, in = ROOT)
151     public void filterClose(NextFilter nextFilter, IoSession session) {
152         nextFilter.filterClose(session);
153     }
154     @IoFilterTransition(on = WRITE, in = ROOT)
155     public void filterWrite(NextFilter nextFilter, IoSession session, WriteRequest writeRequest) {
156         nextFilter.filterWrite(session, writeRequest);
157     }
158 }