1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
36
37
38
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
125
126
127
128
129
130
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 }