View Javadoc

1   /**
2      This file is part of GoldenGate Project (named also GoldenGate or GG).
3   
4      Copyright 2009, Frederic Bregier, and individual contributors by the @author
5      tags. See the COPYRIGHT.txt in the distribution for a full listing of
6      individual contributors.
7   
8      All GoldenGate Project is free software: you can redistribute it and/or 
9      modify it under the terms of the GNU General Public License as published 
10     by the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12  
13     GoldenGate is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17  
18     You should have received a copy of the GNU General Public License
19     along with GoldenGate .  If not, see <http://www.gnu.org/licenses/>.
20   */
21  package goldengate.ftp.exec.adminssl;
22  
23  import goldengate.common.command.ReplyCode;
24  import goldengate.common.command.exception.CommandAbstractException;
25  import goldengate.common.database.DbAdmin;
26  import goldengate.common.database.DbPreparedStatement;
27  import goldengate.common.database.DbSession;
28  import goldengate.common.database.exception.GoldenGateDatabaseException;
29  import goldengate.common.database.exception.GoldenGateDatabaseNoConnectionException;
30  import goldengate.common.database.exception.GoldenGateDatabaseSqlException;
31  import goldengate.common.future.GgFuture;
32  import goldengate.common.logging.GgInternalLogger;
33  import goldengate.common.logging.GgInternalLoggerFactory;
34  import goldengate.common.utility.GgStringUtils;
35  import goldengate.ftp.core.file.FtpDir;
36  import goldengate.ftp.core.session.FtpSession;
37  import goldengate.ftp.core.utils.FtpChannelUtils;
38  import goldengate.ftp.exec.config.FileBasedConfiguration;
39  import goldengate.ftp.exec.control.FtpConstraintLimitHandler;
40  import goldengate.ftp.exec.database.DbConstant;
41  import goldengate.ftp.exec.database.data.DbTransferLog;
42  import goldengate.ftp.exec.exec.AbstractExecutor;
43  import goldengate.ftp.exec.exec.AbstractExecutor.CommandExecutor;
44  import goldengate.ftp.exec.file.FileBasedAuth;
45  import goldengate.ftp.exec.utils.Version;
46  
47  import java.io.IOException;
48  import java.util.List;
49  import java.util.Map;
50  import java.util.Random;
51  import java.util.Set;
52  import java.util.concurrent.ConcurrentHashMap;
53  
54  import openr66.protocol.http.HttpWriteCacheEnable;
55  
56  import org.jboss.netty.buffer.ChannelBuffer;
57  import org.jboss.netty.buffer.ChannelBuffers;
58  import org.jboss.netty.channel.Channel;
59  import org.jboss.netty.channel.ChannelFuture;
60  import org.jboss.netty.channel.ChannelFutureListener;
61  import org.jboss.netty.channel.ChannelHandlerContext;
62  import org.jboss.netty.channel.ChannelStateEvent;
63  import org.jboss.netty.channel.ExceptionEvent;
64  import org.jboss.netty.channel.MessageEvent;
65  import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
66  import org.jboss.netty.channel.group.ChannelGroup;
67  import org.jboss.netty.handler.codec.http.Cookie;
68  import org.jboss.netty.handler.codec.http.CookieDecoder;
69  import org.jboss.netty.handler.codec.http.CookieEncoder;
70  import org.jboss.netty.handler.codec.http.DefaultCookie;
71  import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
72  import org.jboss.netty.handler.codec.http.HttpHeaders;
73  import org.jboss.netty.handler.codec.http.HttpMethod;
74  import org.jboss.netty.handler.codec.http.HttpRequest;
75  import org.jboss.netty.handler.codec.http.HttpResponse;
76  import org.jboss.netty.handler.codec.http.HttpResponseStatus;
77  import org.jboss.netty.handler.codec.http.HttpVersion;
78  import org.jboss.netty.handler.codec.http.QueryStringDecoder;
79  import org.jboss.netty.handler.ssl.SslHandler;
80  import org.jboss.netty.handler.traffic.TrafficCounter;
81  
82  /**
83   * @author Frederic Bregier
84   *
85   */
86  public class HttpSslHandler extends SimpleChannelUpstreamHandler {
87      /**
88       * Internal Logger
89       */
90      private static final GgInternalLogger logger = GgInternalLoggerFactory
91              .getLogger(HttpSslHandler.class);
92      /**
93       * Waiter for SSL handshake is finished
94       */
95      private static final ConcurrentHashMap<Integer, GgFuture> waitForSsl
96          = new ConcurrentHashMap<Integer, GgFuture>();
97      /**
98       * Session Management
99       */
100     private static final ConcurrentHashMap<String, FileBasedAuth> sessions
101         = new ConcurrentHashMap<String, FileBasedAuth>();
102     private static final ConcurrentHashMap<String, DbSession> dbSessions
103         = new ConcurrentHashMap<String, DbSession>();
104     private volatile FtpSession ftpSession =
105         new FtpSession(FileBasedConfiguration.fileBasedConfiguration,
106                 null);
107     private volatile FileBasedAuth authentHttp =
108         new FileBasedAuth(ftpSession);
109 
110     private volatile HttpRequest request;
111     private volatile boolean newSession = false;
112     private volatile Cookie admin = null;
113     private final StringBuilder responseContent = new StringBuilder();
114     private volatile String uriRequest;
115     private volatile Map<String, List<String>> params;
116     private volatile QueryStringDecoder queryStringDecoder;
117     private volatile boolean forceClose = false;
118     private volatile boolean shutdown = false;
119 
120     private static final String FTPSESSION = "FTPSESSION";
121     private static enum REQUEST {
122         Logon("Logon.html"), 
123         index("index.html"),
124         error("error.html"),
125         Transfer("Transfer_head.html","Transfer_body.html","Transfer_end.html"), 
126         Rule("Rule.html"),
127         User("User_head.html","User_body.html","User_end.html"), 
128         System("System.html");
129         
130         private String header;
131         private String body;
132         private String end;
133         /**
134          * Constructor for a unique file
135          * @param uniquefile
136          */
137         private REQUEST(String uniquefile) {
138             this.header = uniquefile;
139             this.body = null;
140             this.end = null;
141         }
142         /**
143          * @param header
144          * @param body
145          * @param end
146          */
147         private REQUEST(String header, String body, String end) {
148             this.header = header;
149             this.body = body;
150             this.end = end;
151         }
152         
153         /**
154          * Reader for a unique file
155          * @return the content of the unique file
156          */
157         public String readFileUnique() {
158             return GgStringUtils.readFile(FileBasedConfiguration.fileBasedConfiguration.httpBasePath+this.header);
159         }
160         
161         public String readHeader() {
162             return GgStringUtils.readFile(FileBasedConfiguration.fileBasedConfiguration.httpBasePath+this.header);
163         }
164         public String readBody() {
165             return GgStringUtils.readFile(FileBasedConfiguration.fileBasedConfiguration.httpBasePath+this.body);
166         }
167         public String readEnd() {
168             return GgStringUtils.readFile(FileBasedConfiguration.fileBasedConfiguration.httpBasePath+this.end);
169         }
170     }
171     public static final int LIMITROW = 48;// better if it can be divided by 4
172 
173     /**
174      * The Database connection attached to this NetworkChannel
175      * shared among all associated LocalChannels in the session
176      */
177     private volatile DbSession dbSession = null;
178     /**
179      * Does this dbSession is private and so should be closed
180      */
181     private volatile boolean isPrivateDbSession = false;
182 
183     /**
184      * Remover from SSL HashMap
185      */
186     private static final ChannelFutureListener remover = new ChannelFutureListener() {
187         public void operationComplete(ChannelFuture future) {
188             logger.debug("SSL remover");
189             waitForSsl.remove(future.getChannel().getId());
190         }
191     };
192 
193     private String getTrimValue(String varname) {
194         String value = params.get(varname).get(0).trim();
195         if (value.length() == 0) {
196             value = null;
197         }
198         return value;
199     }
200     /**
201      * Add the Channel as SSL handshake is over
202      * @param channel
203      */
204     private static void addSslConnectedChannel(Channel channel) {
205         GgFuture futureSSL = new GgFuture(true);
206         waitForSsl.put(channel.getId(),futureSSL);
207         channel.getCloseFuture().addListener(remover);
208     }
209     /**
210      * Set the future of SSL handshake to status
211      * @param channel
212      * @param status
213      */
214     private static void setStatusSslConnectedChannel(Channel channel, boolean status) {
215         GgFuture futureSSL = waitForSsl.get(channel.getId());
216         if (futureSSL != null) {
217             if (status) {
218                 futureSSL.setSuccess();
219             } else {
220                 futureSSL.cancel();
221             }
222         }
223     }
224 
225     /* (non-Javadoc)
226      * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelOpen(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ChannelStateEvent)
227      */
228     @Override
229     public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
230             throws Exception {
231         Channel channel = e.getChannel();
232         logger.debug("Add channel to ssl");
233         addSslConnectedChannel(channel);
234         FileBasedConfiguration.fileBasedConfiguration.getHttpChannelGroup().add(channel);
235         super.channelOpen(ctx, e);
236     }
237 
238     
239 
240     private String index() {
241         String index = REQUEST.index.readFileUnique();
242         StringBuilder builder = new StringBuilder(index);
243         GgStringUtils.replace(builder, "XXXLOCALXXX",
244                 Integer.toString(
245                         FileBasedConfiguration.fileBasedConfiguration.
246                         getFtpInternalConfiguration().getNumberSessions())
247                         +" "+Thread.activeCount());
248         TrafficCounter trafficCounter =
249             FileBasedConfiguration.fileBasedConfiguration.getFtpInternalConfiguration()
250             .getGlobalTrafficShapingHandler().getTrafficCounter();
251         GgStringUtils.replace(builder, "XXXBANDWIDTHXXX",
252                 "IN:"+(trafficCounter.getLastReadThroughput()/131072)+
253                 "Mbits&nbsp;<br>&nbsp;OUT:"+
254                 (trafficCounter.getLastWriteThroughput()/131072)+"Mbits");
255         GgStringUtils.replaceAll(builder, "XXXHOSTIDXXX",
256                 FileBasedConfiguration.fileBasedConfiguration.HOST_ID);
257         GgStringUtils.replaceAll(builder, "XXXADMINXXX",
258                 "Administrator Connected");
259         GgStringUtils.replace(builder, "XXXVERSIONXXX",
260                 Version.ID);
261         return builder.toString();
262     }
263     private String error(String mesg) {
264         String index = REQUEST.error.readFileUnique();
265         return index.replaceAll("XXXERRORMESGXXX",
266                 mesg);
267     }
268     private String Logon() {
269         return REQUEST.Logon.readFileUnique();
270     }
271 
272     private String System() {
273         getParams();
274         FtpConstraintLimitHandler handler = 
275             FileBasedConfiguration.fileBasedConfiguration.constraintLimitHandler;
276         if (params == null) {
277             String system = REQUEST.System.readFileUnique();
278             StringBuilder builder = new StringBuilder(system);
279             GgStringUtils.replace(builder, "XXXXCHANNELLIMITRXXX",
280                     Long.toString(FileBasedConfiguration.fileBasedConfiguration.getServerGlobalReadLimit()));
281             GgStringUtils.replace(builder, "XXXXCPULXXX",
282                     Double.toString(handler.getCpuLimit()));
283             GgStringUtils.replace(builder, "XXXXCONLXXX",
284                     Integer.toString(handler.getChannelLimit()));
285             GgStringUtils.replace(builder, "XXXRESULTXXX", "");
286             return builder.toString();
287         }
288         String extraInformation = null;
289         if (params.containsKey("ACTION")) {
290             List<String> action = params.get("ACTION");
291             for (String act : action) {
292                 if (act.equalsIgnoreCase("Disconnect")) {
293                     String logon = Logon();
294                     newSession = true;
295                     clearSession();
296                     forceClose = true;
297                     return logon;
298                 } else if (act.equalsIgnoreCase("Shutdown")) {
299                     String error = error("Shutdown in progress");
300                     newSession = true;
301                     clearSession();
302                     forceClose = true;
303                     shutdown = true;
304                     return error;
305                 } else if (act.equalsIgnoreCase("Validate")) {
306                     String bglobalr = getTrimValue("BGLOBR");
307                     long lglobal = FileBasedConfiguration.fileBasedConfiguration.getServerGlobalReadLimit();
308                     if (bglobalr != null) {
309                         lglobal = Long.parseLong(bglobalr);
310                     }
311                     FileBasedConfiguration.fileBasedConfiguration.changeNetworkLimit(lglobal, lglobal);
312                     bglobalr = getTrimValue("CPUL");
313                     double dcpu = handler.getCpuLimit();
314                     if (bglobalr != null) {
315                         dcpu = Double.parseDouble(bglobalr);
316                     }
317                     handler.setCpuLimit(dcpu);
318                     bglobalr = getTrimValue("CONL");
319                     int iconn = handler.getChannelLimit();
320                     if (bglobalr != null) {
321                         iconn = Integer.parseInt(bglobalr);
322                     }
323                     handler.setChannelLimit(iconn);
324                     extraInformation = "Configuration Saved";
325                 }
326             }
327         }
328         String system = REQUEST.System.readFileUnique();
329         StringBuilder builder = new StringBuilder(system);
330         GgStringUtils.replace(builder, "XXXXCHANNELLIMITRXXX",
331                 Long.toString(FileBasedConfiguration.fileBasedConfiguration.getServerGlobalReadLimit()));
332         GgStringUtils.replace(builder, "XXXXCPULXXX",
333                 Double.toString(handler.getCpuLimit()));
334         GgStringUtils.replace(builder, "XXXXCONLXXX",
335                 Integer.toString(handler.getChannelLimit()));
336         if (extraInformation != null) {
337             GgStringUtils.replace(builder, "XXXRESULTXXX", extraInformation);
338         } else {
339             GgStringUtils.replace(builder, "XXXRESULTXXX", "");
340         }
341         return builder.toString();
342     }
343 
344     private String Rule() {
345         getParams();
346         if (params == null) {
347             String system = REQUEST.Rule.readFileUnique();
348             StringBuilder builder = new StringBuilder(system);
349             CommandExecutor exec = AbstractExecutor.getCommandExecutor();
350             GgStringUtils.replace(builder, "XXXSTCXXX",
351                     exec.getStorType()+" "+exec.pstorCMD);
352             GgStringUtils.replace(builder, "XXXSTDXXX",
353                     Long.toString(exec.pstorDelay));
354             GgStringUtils.replace(builder, "XXXRTCXXX",
355                     exec.getRetrType()+" "+exec.pretrCMD);
356             GgStringUtils.replace(builder, "XXXRTDXXX",
357                     Long.toString(exec.pretrDelay));
358             GgStringUtils.replace(builder, "XXXRESULTXXX", "");
359             return builder.toString();
360         }
361         String extraInformation = null;
362         if (params.containsKey("ACTION")) {
363             List<String> action = params.get("ACTION");
364             for (String act : action) {
365                 if (act.equalsIgnoreCase("Update")) {
366                     CommandExecutor exec = AbstractExecutor.getCommandExecutor();
367                     String bglobalr = getTrimValue("std");
368                     long lglobal = exec.pstorDelay;
369                     if (bglobalr != null) {
370                         lglobal = Long.parseLong(bglobalr);
371                     }
372                     exec.pstorDelay = lglobal;
373                     bglobalr = getTrimValue("rtd");
374                     lglobal = exec.pretrDelay;
375                     if (bglobalr != null) {
376                         lglobal = Long.parseLong(bglobalr);
377                     }
378                     exec.pretrDelay = lglobal;
379                     bglobalr = getTrimValue("stc");
380                     String store = exec.getStorType()+" "+exec.pstorCMD;
381                     if (bglobalr != null) {
382                         store = bglobalr;
383                     }
384                     bglobalr = getTrimValue("rtc");
385                     String retr = exec.getRetrType()+" "+exec.pretrCMD;
386                     if (bglobalr != null) {
387                         retr = bglobalr;
388                     }
389                     AbstractExecutor.initializeExecutor(retr, exec.pretrDelay, 
390                             store, exec.pstorDelay);
391                     extraInformation = "Configuration Saved";
392                 }
393             }
394         }
395         String system = REQUEST.Rule.readFileUnique();
396         StringBuilder builder = new StringBuilder(system);
397         CommandExecutor exec = AbstractExecutor.getCommandExecutor();
398         GgStringUtils.replace(builder, "XXXSTCXXX",
399                 exec.getStorType()+" "+exec.pstorCMD);
400         GgStringUtils.replace(builder, "XXXSTDXXX",
401                 Long.toString(exec.pstorDelay));
402         GgStringUtils.replace(builder, "XXXRTCXXX",
403                 exec.getRetrType()+" "+exec.pretrCMD);
404         GgStringUtils.replace(builder, "XXXRTDXXX",
405                 Long.toString(exec.pretrDelay));
406         if (extraInformation != null) {
407             GgStringUtils.replace(builder, "XXXRESULTXXX", extraInformation);
408         } else {
409             GgStringUtils.replace(builder, "XXXRESULTXXX", "");
410         }
411         return builder.toString();
412     }
413 
414     private String Transfer() {
415         getParams();
416         String head = REQUEST.Transfer.readHeader();
417         String end = REQUEST.Transfer.readEnd();
418         String body = REQUEST.Transfer.readBody();
419         if (params == null || (!DbConstant.admin.isConnected)) {
420             end = end.replace("XXXRESULTXXX", "");
421             body = FileBasedConfiguration.fileBasedConfiguration.getHtmlTransfer(body, LIMITROW);
422             return head+body+end;
423         }
424         String message = "";
425         List<String> parms = params.get("ACTION");
426         if (parms != null) {
427             String parm = parms.get(0);
428             boolean purgeAll = false;
429             boolean purgeCorrect = false;
430             boolean delete = false;
431             if ("PurgeCorrectTransferLogs".equalsIgnoreCase(parm)) {
432                 purgeCorrect = true;
433             } else if ("PurgeAllTransferLogs".equalsIgnoreCase(parm)) {
434                 purgeAll = true;
435             } else if ("Delete".equalsIgnoreCase(parm)) {
436                 delete = true;
437             }
438             if (purgeCorrect) {
439                 DbPreparedStatement preparedStatement = null;
440                 try {
441                     preparedStatement = 
442                         DbTransferLog.getStatusPrepareStament(dbSession, 
443                                 ReplyCode.REPLY_250_REQUESTED_FILE_ACTION_OKAY, 0);
444                 } catch (GoldenGateDatabaseNoConnectionException e) {
445                     message = "Error during purge";
446                 } catch (GoldenGateDatabaseSqlException e) {
447                     message = "Error during purge";
448                 }
449                 if (preparedStatement != null) {
450                     try {
451                         FileBasedConfiguration config = FileBasedConfiguration.fileBasedConfiguration;
452                         String filename =
453                             config.getBaseDirectory()+
454                             FtpDir.SEPARATOR+config.ADMINNAME+FtpDir.SEPARATOR+
455                             config.HOST_ID+"_logs_"+System.currentTimeMillis()+".xml";
456                         message = DbTransferLog.saveDbTransferLogFile(preparedStatement, filename);
457                     } finally {
458                         preparedStatement.realClose();
459                     }
460                 }
461             } else if (purgeAll) {
462                 DbPreparedStatement preparedStatement = null;
463                 try {
464                     preparedStatement = 
465                         DbTransferLog.getStatusPrepareStament(dbSession, 
466                                 null, 0);
467                 } catch (GoldenGateDatabaseNoConnectionException e) {
468                     message = "Error during purgeAll";
469                 } catch (GoldenGateDatabaseSqlException e) {
470                     message = "Error during purgeAll";
471                 }
472                 if (preparedStatement != null) {
473                     try {
474                         FileBasedConfiguration config = FileBasedConfiguration.fileBasedConfiguration;
475                         String filename =
476                             config.getBaseDirectory()+
477                             FtpDir.SEPARATOR+config.ADMINNAME+FtpDir.SEPARATOR+
478                             config.HOST_ID+"_logs_"+System.currentTimeMillis()+".xml";
479                         message = DbTransferLog.saveDbTransferLogFile(preparedStatement, filename);
480                     } finally {
481                         preparedStatement.realClose();
482                     }
483                 }
484             } else if (delete) {
485                 String user = getTrimValue("user");
486                 String acct = getTrimValue("account");
487                 String specid = getTrimValue("specialid");
488                 long specialId = Long.parseLong(specid);
489                 try {
490                     DbTransferLog log = new DbTransferLog(dbSession, user, acct, specialId);
491                     FileBasedConfiguration config = FileBasedConfiguration.fileBasedConfiguration;
492                     String filename =
493                         config.getBaseDirectory()+
494                         FtpDir.SEPARATOR+config.ADMINNAME+FtpDir.SEPARATOR+
495                         config.HOST_ID+"_log_"+System.currentTimeMillis()+".xml";
496                     message = log.saveDbTransferLog(filename);
497                 } catch (GoldenGateDatabaseException e) {
498                     message = "Error during delete 1 Log";
499                 }
500             } else {
501                 message = "No Action";
502             }
503             end = end.replace("XXXRESULTXXX", message);
504         }
505         end = end.replace("XXXRESULTXXX", "");
506         body = FileBasedConfiguration.fileBasedConfiguration.getHtmlTransfer(body, LIMITROW);
507         return head+body+end;
508     }
509     private String User() {
510         getParams();
511         String head = REQUEST.User.readHeader();
512         String end = REQUEST.User.readEnd();
513         String body = REQUEST.User.readBody();
514         FileBasedConfiguration config = FileBasedConfiguration.fileBasedConfiguration;
515         String filedefault = config.getBaseDirectory()+
516                 FtpDir.SEPARATOR+config.ADMINNAME+
517                 FtpDir.SEPARATOR+"authentication.xml";
518         if (params == null) {
519             end = end.replace("XXXRESULTXXX", "");
520             end = end.replace("XXXFILEXXX", filedefault);
521             body = FileBasedConfiguration.fileBasedConfiguration.getHtmlAuth(body);
522             return head+body+end;
523         }
524         List<String> parms = params.get("ACTION");
525         if (parms != null) {
526             String parm = parms.get(0);
527             if ("ImportExport".equalsIgnoreCase(parm)) {
528                 String file = getTrimValue("file");
529                 String exportImport = getTrimValue("export");
530                 String message = "";
531                 boolean purge = false;
532                 purge = params.containsKey("purge");
533                 boolean replace = false;
534                 replace = params.containsKey("replace");
535                 if (file == null) {
536                     file = filedefault;
537                 }
538                 end = end.replace("XXXFILEXXX", file);
539                 if (exportImport.equalsIgnoreCase("import")) {
540                     if (! config.initializeAuthent(file, purge)) {
541                         message += "Cannot initialize Authentication from "+file;
542                     } else {
543                         message += "Initialization of Authentication OK from "+file;
544                         if (replace) {
545                             if (! config.saveAuthenticationFile(
546                                     config.authenticationFile)) {
547                                 message += " but cannot replace server authenticationFile";
548                             } else {
549                                 message += " and replacement done";
550                             }
551                         }
552                     }
553                 } else {
554                     // export
555                     if (! config.saveAuthenticationFile(file)) {
556                         message += "Authentications CANNOT be saved into "+file;
557                     } else {
558                         message += "Authentications saved into "+file;
559                     }
560                 }
561                 end = end.replace("XXXRESULTXXX", message);
562             } else {
563                 end = end.replace("XXXFILEXXX", filedefault);
564             }
565         }
566         end = end.replace("XXXRESULTXXX", "");
567         body = FileBasedConfiguration.fileBasedConfiguration.getHtmlAuth(body);
568         return head+body+end;
569     }
570     private void getParams() {
571         if (request.getMethod() == HttpMethod.GET) {
572             params = null;
573         } else if (request.getMethod() == HttpMethod.POST) {
574             ChannelBuffer content = request.getContent();
575             if (content.readable()) {
576                 String param = content.toString(GgStringUtils.UTF8);
577                 QueryStringDecoder queryStringDecoder2 = new QueryStringDecoder("/?"+param);
578                 params = queryStringDecoder2.getParameters();
579             } else {
580                 params = null;
581             }
582         }
583     }
584     private void clearSession() {
585         if (admin != null) {
586             FileBasedAuth auth = sessions.remove(admin.getValue());
587             DbSession ldbsession = dbSessions.remove(admin.getValue());
588             admin = null;
589             if (auth != null) {
590                 auth.clear();
591             }
592             if (ldbsession != null) {
593                 ldbsession.disconnect();
594                 DbAdmin.nbHttpSession--;
595             }
596         }
597     }
598     private void checkAuthent(MessageEvent e) {
599         newSession = true;
600         if (request.getMethod() == HttpMethod.GET) {
601             String logon = Logon();
602             responseContent.append(logon);
603             clearSession();
604             writeResponse(e.getChannel());
605             return;
606         } else if (request.getMethod() == HttpMethod.POST) {
607             getParams();
608             if (params == null) {
609                 String logon = Logon();
610                 responseContent.append(logon);
611                 clearSession();
612                 writeResponse(e.getChannel());
613                 return;
614             }
615         }
616         boolean getMenu = false;
617         if (params.containsKey("Logon")) {
618             String name = null, password = null;
619             List<String> values = null;
620             if (!params.isEmpty()) {
621                 // get values
622                 if (params.containsKey("name")) {
623                     values = params.get("name");
624                     if (values != null) {
625                         name = values.get(0);
626                         if (name == null || name.length() == 0) {
627                             getMenu = true;
628                         }
629                     }
630                 } else {
631                     getMenu = true;
632                 }
633                 // search the nb param
634                 if ((!getMenu) && params.containsKey("passwd")) {
635                     values = params.get("passwd");
636                     if (values != null) {
637                         password = values.get(0);
638                         if (password == null || password.length() == 0) {
639                             getMenu = true;
640                         } else {
641                             getMenu = false;
642                         }
643                     } else {
644                         getMenu = true;
645                     }
646                 } else {
647                     getMenu = true;
648                 }
649             } else {
650                 getMenu = true;
651             }
652             if (! getMenu) {
653                 logger.debug("Name="+name+" vs "+name.equals(FileBasedConfiguration.fileBasedConfiguration.ADMINNAME)+
654                         " Passwd="+password+" vs "+
655                                 FileBasedConfiguration.fileBasedConfiguration.checkPassword(password));
656                 if (name.equals(FileBasedConfiguration.fileBasedConfiguration.ADMINNAME) &&
657                         FileBasedConfiguration.fileBasedConfiguration.checkPassword(password)) {
658                     authentHttp.specialNoSessionAuth(FileBasedConfiguration.fileBasedConfiguration.HOST_ID);
659                 } else {
660                     getMenu = true;
661                 }
662                 if (! authentHttp.isIdentified()) {
663                     logger.debug("Still not authenticated: {}",authentHttp);
664                     getMenu = true;
665                 }
666                 // load DbSession
667                 if (this.dbSession == null) {
668                     try {
669                         if (DbConstant.admin.isConnected) {
670                             this.dbSession = new DbSession(DbConstant.admin, false);
671                             DbAdmin.nbHttpSession++;
672                             this.isPrivateDbSession = true;
673                         }
674                     } catch (GoldenGateDatabaseNoConnectionException e1) {
675                         // Cannot connect so use default connection
676                         logger.warn("Use default database connection");
677                         this.dbSession = DbConstant.admin.session;
678                     }
679                 }
680             }
681         } else {
682             getMenu = true;
683         }
684         if (getMenu) {
685             String logon = Logon();
686             responseContent.append(logon);
687             clearSession();
688             writeResponse(e.getChannel());
689         } else {
690             String index = index();
691             responseContent.append(index);
692             clearSession();
693             admin = new DefaultCookie(FTPSESSION, 
694                     FileBasedConfiguration.fileBasedConfiguration.HOST_ID+
695                     Long.toHexString(new Random().nextLong()));
696             sessions.put(admin.getValue(), this.authentHttp);
697             if (this.isPrivateDbSession) {
698                 dbSessions.put(admin.getValue(), dbSession);
699             }
700             logger.debug("CreateSession: "+uriRequest+":{}",admin);
701             writeResponse(e.getChannel());
702         }
703     }
704 
705     @Override
706     public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
707             HttpRequest request = this.request = (HttpRequest) e.getMessage();
708             queryStringDecoder = new QueryStringDecoder(request.getUri());
709             uriRequest = queryStringDecoder.getPath();
710             if (uriRequest.contains("gre/") || uriRequest.contains("img/") ||
711                     uriRequest.contains("res/")) {
712                 HttpWriteCacheEnable.writeFile(request, 
713                         e.getChannel(), 
714                         FileBasedConfiguration.fileBasedConfiguration.httpBasePath+uriRequest,
715                         FTPSESSION);
716                 return;
717             }
718             checkSession(e.getChannel());
719             if (! authentHttp.isIdentified()) {
720                 logger.debug("Not Authent: "+uriRequest+":{}",authentHttp);
721                 checkAuthent(e);
722                 return;
723             }
724             String find = uriRequest;
725             if (uriRequest.charAt(0) == '/') {
726                 find = uriRequest.substring(1);
727             }
728             find = find.substring(0, find.indexOf("."));
729             REQUEST req = REQUEST.index;
730             try {
731                 req = REQUEST.valueOf(find);
732             } catch (IllegalArgumentException e1) {
733                 req = REQUEST.index;
734                 logger.debug("NotFound: "+find+":"+uriRequest);
735             }
736             switch (req) {
737                 case index:
738                     responseContent.append(index());
739                     break;
740                 case Logon:
741                     responseContent.append(index());
742                     break;
743                 case System:
744                     responseContent.append(System());
745                     break;
746                 case Rule:
747                     responseContent.append(Rule());
748                     break;
749                 case User:
750                     responseContent.append(User());
751                     break;
752                 case Transfer:
753                     responseContent.append(Transfer());
754                     break;
755                 default:
756                     responseContent.append(index());
757                     break;
758             }
759             writeResponse(e.getChannel());
760     }
761     private void checkSession(Channel channel) {
762         String cookieString = request.getHeader(HttpHeaders.Names.COOKIE);
763         if (cookieString != null) {
764             CookieDecoder cookieDecoder = new CookieDecoder();
765             Set<Cookie> cookies = cookieDecoder.decode(cookieString);
766             if(!cookies.isEmpty()) {
767                 for (Cookie elt : cookies) {
768                     if (elt.getName().equalsIgnoreCase(FTPSESSION)) {
769                         admin = elt;
770                         break;
771                     }
772                 }
773             }
774         }
775         if (admin != null) {
776             FileBasedAuth auth = sessions.get(admin.getValue());
777             if (auth != null) {
778                 authentHttp = auth;
779             }
780             DbSession dbSession = dbSessions.get(admin.getValue());
781             if (dbSession != null) {
782                 this.dbSession = dbSession;
783             }
784         } else {
785             logger.debug("NoSession: "+uriRequest+":{}",admin);
786         }
787     }
788     private void handleCookies(HttpResponse response) {
789         String cookieString = request.getHeader(HttpHeaders.Names.COOKIE);
790         if (cookieString != null) {
791             CookieDecoder cookieDecoder = new CookieDecoder();
792             Set<Cookie> cookies = cookieDecoder.decode(cookieString);
793             if(!cookies.isEmpty()) {
794                 // Reset the sessions if necessary.
795                 CookieEncoder cookieEncoder = new CookieEncoder(true);
796                 boolean findSession = false;
797                 for (Cookie cookie : cookies) {
798                     if (cookie.getName().equalsIgnoreCase(FTPSESSION)) {
799                         if (newSession) {
800                             findSession = false;
801                         } else {
802                             findSession = true;
803                             cookieEncoder.addCookie(cookie);
804                             response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
805                             cookieEncoder = new CookieEncoder(true);
806                         }
807                     } else {
808                         cookieEncoder.addCookie(cookie);
809                         response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
810                         cookieEncoder = new CookieEncoder(true);
811                     }
812                 }
813                 newSession = false;
814                 if (! findSession) {
815                     if (admin != null) {
816                         cookieEncoder.addCookie(admin);
817                         response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
818                         cookieEncoder = new CookieEncoder(true);
819                         logger.debug("AddSession: "+uriRequest+":{}",admin);
820                     }
821                 }
822             }
823         } else if (admin != null) {
824             CookieEncoder cookieEncoder = new CookieEncoder(true);
825             cookieEncoder.addCookie(admin);
826             logger.debug("AddSession: "+uriRequest+":{}",admin);
827             response.addHeader(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
828         }
829     }
830     /**
831      * Write the response
832      * @param e
833      */
834     private void writeResponse(Channel channel) {
835         // Convert the response content to a ChannelBuffer.
836         ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), GgStringUtils.UTF8);
837         responseContent.setLength(0);
838 
839         // Decide whether to close the connection or not.
840         boolean keepAlive = HttpHeaders.isKeepAlive(request);
841         boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request
842                 .getHeader(HttpHeaders.Names.CONNECTION)) ||
843                 (!keepAlive) || forceClose;
844 
845         // Build the response object.
846         HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
847         response.setContent(buf);
848         response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/html");
849         if (keepAlive) {
850             response.setHeader(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
851         }
852         if (!close) {
853             // There's no need to add 'Content-Length' header
854             // if this is the last response.
855             response.setHeader(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
856         }
857 
858         handleCookies(response);
859 
860         // Write the response.
861         ChannelFuture future = channel.write(response);
862         // Close the connection after the write operation is done if necessary.
863         if (close) {
864             future.addListener(ChannelFutureListener.CLOSE);
865         }
866         if (shutdown) {
867             /*
868               Thread thread = 
869              
870                 new Thread(
871                         new FtpChannelUtils(
872                                 FileBasedConfiguration.fileBasedConfiguration));
873             thread.setDaemon(true);
874             thread.setName("Shutdown Thread");
875             thread.start();
876             */
877             FtpChannelUtils.teminateServer(FileBasedConfiguration.fileBasedConfiguration);
878             if (! close){
879                 future.addListener(ChannelFutureListener.CLOSE);
880             }
881         }
882     }
883     /**
884      * Send an error and close
885      * @param ctx
886      * @param status
887      */
888     private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
889         HttpResponse response = new DefaultHttpResponse(
890                 HttpVersion.HTTP_1_1, status);
891         response.setHeader(
892                 HttpHeaders.Names.CONTENT_TYPE, "text/html");
893         responseContent.setLength(0);
894         responseContent.append(error(status.toString()));
895         response.setContent(ChannelBuffers.copiedBuffer(responseContent.toString(), GgStringUtils.UTF8));
896         clearSession();
897         // Close the connection as soon as the error message is sent.
898         ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
899     }
900 
901     @Override
902     public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
903             throws Exception {
904         Throwable e1 = e.getCause();
905         if (!(e1 instanceof CommandAbstractException)) {
906             if (e1 instanceof IOException) {
907                 // Nothing to do
908                 return;
909             }
910             logger.warn("Exception in HttpSslHandler", e1);
911         }
912         if (e.getChannel().isConnected()) {
913             sendError(ctx, HttpResponseStatus.BAD_REQUEST);
914         }
915     }
916 
917     /* (non-Javadoc)
918      * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelConnected(org.jboss.netty.channel.ChannelHandlerContext, org.jboss.netty.channel.ChannelStateEvent)
919      */
920     @Override
921     public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
922             throws Exception {
923         // Get the SslHandler in the current pipeline.
924         // We added it in NetworkSslServerPipelineFactory.
925         final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
926         if (sslHandler != null) {
927             // Get the SslHandler and begin handshake ASAP.
928             // Get notified when SSL handshake is done.
929             ChannelFuture handshakeFuture;
930             handshakeFuture = sslHandler.handshake();
931             if (handshakeFuture != null) {
932                 handshakeFuture.addListener(new ChannelFutureListener() {
933                     public void operationComplete(ChannelFuture future)
934                             throws Exception {
935                         logger.debug("Handshake: "+future.isSuccess(),future.getCause());
936                         if (future.isSuccess()) {
937                             setStatusSslConnectedChannel(future.getChannel(), true);
938                         } else {
939                             setStatusSslConnectedChannel(future.getChannel(), false);
940                             future.getChannel().close();
941                         }
942                     }
943                 });
944             }
945         } else {
946             logger.warn("SSL Not found");
947         }
948         super.channelConnected(ctx, e);
949         ChannelGroup group =
950             FileBasedConfiguration.fileBasedConfiguration.getHttpChannelGroup();
951         if (group != null) {
952             group.add(e.getChannel());
953         }
954     }
955 }