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