KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > alfresco > filesys > server > auth > passthru > PassthruServers


1 /*
2  * Copyright (C) 2006 Alfresco, Inc.
3  *
4  * Licensed under the Mozilla Public License version 1.1
5  * with a permitted attribution clause. You may obtain a
6  * copy of the License at
7  *
8  * http://www.alfresco.org/legal/license.txt
9  *
10  * Unless required by applicable law or agreed to in writing,
11  * software distributed under the License is distributed on an
12  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13  * either express or implied. See the License for the specific
14  * language governing permissions and limitations under the
15  * License.
16  */

17 package org.alfresco.filesys.server.auth.passthru;
18
19 import java.io.IOException JavaDoc;
20 import java.net.InetAddress JavaDoc;
21 import java.net.UnknownHostException JavaDoc;
22 import java.util.*;
23
24 import org.alfresco.error.AlfrescoRuntimeException;
25 import org.alfresco.filesys.netbios.NetBIOSName;
26 import org.alfresco.filesys.netbios.NetBIOSNameList;
27 import org.alfresco.filesys.netbios.NetBIOSSession;
28 import org.alfresco.filesys.smb.PCShare;
29 import org.alfresco.filesys.util.IPAddress;
30 import org.apache.log4j.*;
31
32 /**
33  * Passthru Servers Class
34  *
35  * <p>Contains a list of one or more servers that are used for passthru authentication. The status of the
36  * servers is tracked so that offline servers are not used but periodically monitored so that they can be
37  * returned to the online list of servers.
38  *
39  * <p>The server list may be initialized from a list of server names or addresses, or by specifying a domain
40  * name in which case the primary and backup domain controllers will be used.
41  *
42  * @author GKSpencer
43  *
44  */

45 public class PassthruServers
46 {
47     // Debug logging
48

49     private static final Logger logger = Logger.getLogger("org.alfresco.smb.protocol.auth");
50
51     // Default timeout for setting up a new session
52

53     private static final int DefaultConnectTimeout = 5000; // 5 seconds
54

55     // Default interval to check if offline servers
56

57     private static final long DefaultOfflineCheckInterval = 5 * 60000; // 5 minutes
58

59     // List of online and offline authentication servers
60

61     private List<PassthruServerDetails> m_onlineList;
62     private List<PassthruServerDetails> m_offlineList;
63     
64     // Timeout value when opening a session to an authentication server, in milliseconds
65

66     private int m_tmo = DefaultConnectTimeout;
67     
68     // Domain name, if using domain controllers
69

70     private String JavaDoc m_domain;
71     
72     // Offline server check interval
73

74     private long m_offlineCheckInterval = DefaultOfflineCheckInterval;
75
76     // Offline server checker thread
77

78     PassthruOfflineChecker m_offlineChecker;
79     
80     /**
81      * Inner class used to periodically check offline servers to see if they are back online
82      */

83     class PassthruOfflineChecker extends Thread JavaDoc
84     {
85         // Thread shutdown request flag
86

87         private boolean m_ishutdown;
88         
89         /**
90          * Default constructor
91          */

92         PassthruOfflineChecker()
93         {
94             setDaemon(true);
95             setName("PassthruOfflineChecker");
96             start();
97         }
98         
99         /**
100          * Main thread code
101          */

102         public void run()
103         {
104             // Loop until shutdown
105

106             m_ishutdown = false;
107             
108             while ( m_ishutdown == false)
109             {
110                 // Sleep for a while
111

112                 try
113                 {
114                     sleep( m_offlineCheckInterval);
115                 }
116                 catch ( InterruptedException JavaDoc ex)
117                 {
118                 }
119                 
120                 // Check if shutdown has been requested
121

122                 if( m_ishutdown == true)
123                     continue;
124                 
125                 // Check if there are any offline servers to check
126

127                 if ( getOfflineServerCount() > 0)
128                 {
129                     // Enumerate the offline server list
130

131                     int idx = 0;
132                     PassthruServerDetails offlineServer = null;
133                     PCShare authShare = new PCShare("", "IPC$", "", "");
134                     AuthenticateSession authSess = null;
135                     
136                     while ( idx < getOfflineServerCount())
137                     {
138                         // Get an offline server from the list
139

140                         offlineServer = m_offlineList.get(idx);
141                         
142                         if ( offlineServer != null)
143                         {
144                             try
145                             {
146                                 // Set the target host name
147

148                                 authShare.setNodeName(offlineServer.getAddress().getHostAddress());
149                                 
150                                 // Try and connect to the authentication server
151

152                                 authSess = AuthSessionFactory.OpenAuthenticateSession( authShare, getConnectionTimeout());
153                                 
154                                 // Close the session
155

156                                 try
157                                 {
158                                     authSess.CloseSession();
159                                 }
160                                 catch ( Exception JavaDoc ex)
161                                 {
162                                 }
163                                 
164                                 // Authentication server is online, move it to the online list
165

166                                 serverOnline(offlineServer);
167                             }
168                             catch ( Exception JavaDoc ex)
169                             {
170                                 // Debug
171

172                                 if ( logger.isDebugEnabled())
173                                     logger.debug("Passthru offline check failed for " + offlineServer.getName());
174                             }
175                             
176                             // Check if the server is now online
177

178                             if ( offlineServer.isOnline() == false)
179                                 idx++;
180                         }
181                     }
182                 }
183             }
184             
185             // Debug
186

187             if( logger.isDebugEnabled())
188                 logger.debug("Passthru offline checker thread closed");
189         }
190         
191         /**
192          * Shutdown the checker thread
193          */

194         public final void shutdownRequest()
195         {
196             m_ishutdown = true;
197             this.interrupt();
198         }
199         
200         /**
201          * Wakeup the offline checker thread to process the offline server list
202          */

203         public final void processOfflineServers()
204         {
205             this.interrupt();
206         }
207     }
208     
209     /**
210      * Default constructor
211      */

212     public PassthruServers()
213     {
214         // Create the server lists
215

216         m_onlineList = new ArrayList<PassthruServerDetails>();
217         m_offlineList = new ArrayList<PassthruServerDetails>();
218         
219         // Create and start the offline server checker thread
220

221         m_offlineChecker = new PassthruOfflineChecker();
222     }
223     
224     /**
225      * Return the count of online authentication servers
226      *
227      * @return int
228      */

229     public final int getOnlineServerCount()
230     {
231         return m_onlineList.size();
232     }
233     
234     /**
235      * Return the count of offline authentication servers
236      *
237      * @return int
238      */

239     public final int getOfflineServerCount()
240     {
241         return m_offlineList.size();
242     }
243     
244     /**
245      * Return the total count of online and offline servers
246      *
247      * @return int
248      */

249     public final int getTotalServerCount()
250     {
251         return m_onlineList.size() + m_offlineList.size();
252     }
253     
254     /**
255      * Determine if there are online servers
256      *
257      * @return boolean
258      */

259     public final boolean hasOnlineServers()
260     {
261         return m_onlineList.size() > 0 ? true : false;
262     }
263     
264     /**
265      * Return the connection timeout, in milliseconds
266      *
267      * @return int
268      */

269     public final int getConnectionTimeout()
270     {
271         return m_tmo;
272     }
273     
274     /**
275      * Determine if the authentication servers are domain controllers
276      *
277      * @return boolean
278      */

279     public final boolean isDomainAuthentication()
280     {
281         return m_domain != null ? true : false;
282     }
283     
284     /**
285      * Return the domain name
286      *
287      * @return String
288      */

289     public final String JavaDoc getDomain()
290     {
291         return m_domain;
292     }
293     
294     /**
295      * Open a new session to an authentication server
296      *
297      * @return AuthenticateSession
298      */

299     public final AuthenticateSession openSession()
300     {
301         return openSession( 0);
302     }
303     
304     /**
305      * Open a new session to an authentication server
306      *
307      * @param extFlags int
308      * @return AuthenticateSession
309      */

310     public final AuthenticateSession openSession(int extFlags)
311     {
312         // Get the details of an authentication server to connect to
313

314         PassthruServerDetails passthruServer = getAuthenticationServer();
315         if ( passthruServer == null)
316             return null;
317
318         // Debug
319

320         if ( logger.isDebugEnabled())
321             logger.debug("Open authenticate session to " + passthruServer);
322         
323         // Open a new authentication session to the server
324

325         PCShare authShare = new PCShare(passthruServer.getAddress().getHostAddress(), "IPC$", "", "");
326         authShare.setExtendedSecurityFlags( extFlags);
327         
328         AuthenticateSession authSess = null;
329         
330         while ( authSess == null && passthruServer != null && hasOnlineServers()) {
331
332             try
333             {
334                 // Open a session to the current authentication server
335

336                 authSess = AuthSessionFactory.OpenAuthenticateSession( authShare, getConnectionTimeout());
337                 
338                 // Update the passthru statistics
339

340                 passthruServer.incrementAuthenticationCount();
341             }
342             catch ( Exception JavaDoc ex)
343             {
344                 // Debug
345

346                 if ( logger.isDebugEnabled())
347                     logger.debug("Failed to connect to " + passthruServer + " : " + ex.getMessage());
348                 
349                 // Failed to connect to the current authentication server, mark the server as offline
350

351                 serverOffline(passthruServer);
352             }
353             
354             // Check if we have a valid session
355

356             if ( authSess == null)
357             {
358                 // Try another authentication server
359

360                 passthruServer = getAuthenticationServer();
361                 
362                 // Debug
363

364                 if(logger.isDebugEnabled())
365                     logger.debug("Trying authentication server " + passthruServer);
366             }
367         }
368
369         // Return the authentication session
370

371         return authSess;
372     }
373     
374     /**
375      * Return the details of an online server to use for authentication
376      *
377      * @return PassthruServerDetails
378      */

379     protected PassthruServerDetails getAuthenticationServer()
380     {
381         // Rotate the head of the list and return the new head of list server details
382

383         PassthruServerDetails passthruServer = null;
384
385         synchronized ( m_onlineList)
386         {
387             if ( m_onlineList.size() > 1)
388                 m_onlineList.add(m_onlineList.remove(0));
389             if ( m_onlineList.size() > 0)
390                 passthruServer = m_onlineList.get(0);
391         }
392         
393         return passthruServer;
394     }
395     
396     /**
397      * Move a server from the list of online servers to the offline list
398      *
399      * @param server PassthruServerDetails
400      */

401     protected final void serverOffline(PassthruServerDetails server)
402     {
403         // Set the server status
404

405         server.setOnline(false);
406         
407         // Remove the server from the online list
408

409         synchronized( m_onlineList)
410         {
411             m_onlineList.remove(server);
412         }
413         
414         // Add it to the offline list
415

416         synchronized( m_offlineList)
417         {
418             m_offlineList.add( server);
419         }
420         
421         // Debug
422

423         if ( logger.isDebugEnabled())
424             logger.debug("Passthru server offline, " + server);
425     }
426     
427     /**
428      * Move a server from the list of offline servers to the online list
429      *
430      * @param server PassthruServerDetails
431      */

432     protected final void serverOnline(PassthruServerDetails server)
433     {
434         // Set the server status
435

436         server.setOnline(true);
437         
438         // Remove the server from the offline list
439

440         synchronized( m_offlineList)
441         {
442             m_offlineList.remove(server);
443         }
444         
445         // Add it to the online list
446

447         synchronized( m_onlineList)
448         {
449             m_onlineList.add( server);
450         }
451         
452         // Debug
453

454         if ( logger.isDebugEnabled())
455             logger.debug("Passthru server online, " + server);
456     }
457     
458     /**
459      * Set the session connect timeout value, in milliseconds
460      *
461      * @param tmo int
462      */

463     public final void setConnectionTimeout(int tmo)
464     {
465         m_tmo = tmo;
466     }
467
468     /**
469      * Set the offline check interval, in seconds
470      *
471      * @param interval long
472      */

473     public final void setOfflineCheckInterval(long interval)
474     {
475         m_offlineCheckInterval = interval * 1000L;
476     }
477     
478     /**
479      * Set the list of servers to use for passthru authentication using a comma delimeted list
480      * of server names/addresses
481      *
482      * @param servers String
483      */

484     public final void setServerList(String JavaDoc servers)
485     {
486         // Split the server list into seperate name/address tokens
487

488         StringTokenizer tokens = new StringTokenizer(servers, ",");
489         
490         while ( tokens.hasMoreTokens())
491         {
492             // Get the current server name/address
493

494             String JavaDoc srvName = tokens.nextToken().trim();
495             
496             // If a name a has been specified convert it to an address, if an address has been specified
497
// then convert to a name.
498

499             InetAddress JavaDoc srvAddr = null;
500             
501             if ( IPAddress.isNumericAddress(srvName))
502             {
503                 // Get the server name
504

505                 try
506                 {
507                     // Get the host address and name
508

509                     srvAddr = InetAddress.getByName(srvName);
510                     srvName = srvAddr.getHostName();
511                 }
512                 catch ( UnknownHostException JavaDoc ex)
513                 {
514                     // Debug
515

516                     if ( logger.isDebugEnabled())
517                         logger.debug("Passthru failed to find name/address for " + srvName);
518                 }
519             }
520             else
521             {
522                 // Get the server address
523

524                 try
525                 {
526                     srvAddr = InetAddress.getByName(srvName);
527                 }
528                 catch ( UnknownHostException JavaDoc ex)
529                 {
530                     // Debug
531

532                     if ( logger.isDebugEnabled())
533                         logger.debug("Passthru failed to find address for " + srvName);
534                 }
535             }
536             
537             // Create the passthru server details and add to the list of offline servers
538

539             if ( srvName != null && srvAddr != null)
540             {
541                 // Create the passthru server details
542

543                 PassthruServerDetails passthruServer = new PassthruServerDetails(srvName, null, srvAddr, false);
544                 m_offlineList.add( passthruServer);
545                 
546                 // Debug
547

548                 if ( logger.isDebugEnabled())
549                     logger.debug("Added passthru server " + passthruServer);
550             }
551         }
552         
553         // Wakeup the server checker thread to check each of the servers just added and move servers that are
554
// accessible to the online list
555

556         m_offlineChecker.processOfflineServers();
557     }
558     
559     /**
560      * Set the domain to use for passthru authentication
561      *
562      * @param domain String
563      */

564     public final void setDomain(String JavaDoc domain)
565     {
566
567         // DEBUG
568

569         if (logger.isDebugEnabled())
570             logger.debug("Passthru finding domain controller for " + domain + " ...");
571
572         // Find a domain controller or the browse master
573

574         NetBIOSName nbName = null;
575         
576         try
577         {
578             // Find a domain controller
579

580             nbName = NetBIOSSession.FindName(domain, NetBIOSName.DomainControllers, getConnectionTimeout());
581
582             // DEBUG
583

584             if (logger.isDebugEnabled())
585                 logger.debug(" Found " + nbName.numberOfAddresses() + " domain controller(s)");
586         }
587         catch (IOException JavaDoc ex)
588         {
589         }
590
591         // If we did not find a domain controller look for the browse master
592

593         if ( nbName == null) {
594             
595             try
596             {
597                 // Try and find the browse master for the workgroup
598

599                 nbName = NetBIOSSession.FindName( domain, NetBIOSName.MasterBrowser, getConnectionTimeout());
600                 
601                 // DEBUG
602

603                 if (logger.isDebugEnabled())
604                     logger.debug(" Found browse master at " + nbName.getIPAddressString(0));
605             }
606             catch (IOException JavaDoc ex)
607             {
608                 throw new AlfrescoRuntimeException("Failed to find domain controller or browse master for " + domain);
609             }
610         }
611
612         // Add the passthru server(s)
613
//
614
// Try and convert the address to a name for each domain controller
615

616         for ( int i = 0; i < nbName.numberOfAddresses(); i++)
617         {
618             // Get the domain controller name
619

620             InetAddress JavaDoc dcAddr = null;
621             String JavaDoc dcName = null;
622             
623             try
624             {
625                 // Get the current domain controller address
626

627                 dcAddr = InetAddress.getByName(nbName.getIPAddressString(i));
628                 
629                 // Get the list of NetBIOS names for the domain controller
630

631                 NetBIOSNameList nameList = NetBIOSSession.FindNamesForAddress(dcAddr.getHostAddress());
632                 NetBIOSName dcNBName = nameList.findName(NetBIOSName.FileServer, false);
633                 
634                 if ( dcNBName != null)
635                     dcName = dcNBName.getName();
636             }
637             catch (UnknownHostException JavaDoc ex)
638             {
639                 // Debug
640

641                 if ( logger.isDebugEnabled())
642                      logger.debug("Invalid address for server " + nbName.getIPAddressString(i));
643             }
644             catch (Exception JavaDoc ex)
645             {
646                 // Failed to get domain controller name, use the address
647

648                 dcName = dcAddr.getHostAddress();
649                 
650                 // Debug
651

652                 if ( logger.isDebugEnabled())
653                     logger.debug("Failed to get NetBIOS name for server " + dcAddr);
654             }
655             
656             // Create a passthru server entry for the domain controller
657

658             if ( dcAddr != null)
659             {
660                 // Create the passthru authentication server record
661

662                 PassthruServerDetails passthruServer = new PassthruServerDetails(dcName, domain, dcAddr, false);
663                 m_offlineList.add(passthruServer);
664                 
665                 // Debug
666

667                 if ( logger.isDebugEnabled())
668                     logger.debug("Added passthru server " + passthruServer);
669             }
670         }
671         
672         // Wakeup the server checker thread to check each of the servers just added and move servers that are
673
// accessible to the online list
674

675         m_offlineChecker.processOfflineServers();
676     }
677     
678     /**
679      * Shutdown passthru authentication
680      */

681     public final void shutdown()
682     {
683         // Shutdown the offline server checker thread
684

685         m_offlineChecker.shutdownRequest();
686         
687         // Clear the online and offline server lists
688

689         m_onlineList.clear();
690         m_offlineList.clear();
691     }
692     
693     /**
694      * Return the passthru server details as a string
695      *
696      * @return String
697      */

698     public String JavaDoc toString()
699     {
700         StringBuilder JavaDoc str = new StringBuilder JavaDoc();
701         
702         str.append("[");
703         
704         if ( isDomainAuthentication())
705         {
706             str.append("Domain:");
707             str.append(getDomain());
708         }
709         else
710             str.append("Servers:");
711         
712         str.append(",Online=");
713         str.append(getOnlineServerCount());
714         str.append(",Offline=");
715         str.append(getOfflineServerCount());
716         str.append("]");
717         
718         return str.toString();
719     }
720 }
721
Popular Tags