KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > go > teaservlet > AdminApplication


1 /* ====================================================================
2  * TeaServlet - Copyright (c) 1999-2000 Walt Disney Internet Group
3  * ====================================================================
4  * The Tea Software License, Version 1.1
5  *
6  * Copyright (c) 2000 Walt Disney Internet Group. All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Walt Disney Internet Group (http://opensource.go.com/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Tea", "TeaServlet", "Kettle", "Trove" and "BeanDoc" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact opensource@dig.com.
31  *
32  * 5. Products derived from this software may not be called "Tea",
33  * "TeaServlet", "Kettle" or "Trove", nor may "Tea", "TeaServlet",
34  * "Kettle", "Trove" or "BeanDoc" appear in their name, without prior
35  * written permission of the Walt Disney Internet Group.
36  *
37  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40  * DISCLAIMED. IN NO EVENT SHALL THE WALT DISNEY INTERNET GROUP OR ITS
41  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
42  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
43  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
44  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
45  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
47  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  * ====================================================================
49  *
50  * For more information about Tea, please see http://opensource.go.com/.
51  */

52
53 package com.go.teaservlet;
54
55 import java.beans.*;
56 import java.io.*;
57 import java.util.*;
58 import java.net.*;
59 import javax.servlet.ServletConfig JavaDoc;
60 import javax.servlet.ServletContext JavaDoc;
61 import javax.servlet.ServletException JavaDoc;
62 import javax.servlet.http.Cookie JavaDoc;
63
64 import com.go.trove.log.Log;
65 import com.go.trove.util.BeanComparator;
66 import com.go.trove.io.CharToByteBuffer;
67 import com.go.trove.io.ByteBuffer;
68 import com.go.tea.util.BeanAnalyzer;
69 import com.go.teatools.*;
70 import com.go.teaservlet.util.ObjectIdentifier;
71 //REMOTE stuff
72
import java.rmi.RemoteException JavaDoc;
73 import com.go.teaservlet.util.cluster.Restartable;
74 import com.go.teaservlet.util.cluster.Clustered;
75 import com.go.teaservlet.util.cluster.ClusterManager;
76 import com.go.teaservlet.util.cluster.TeaServletClusterHook;
77
78 /******************************************************************************
79  * The Admin application defines functions for administering the TeaServlet.
80  *
81  * @author Reece Wilton, Brian S O'Neill, Jonathan Colwell
82  * @version
83  * <!--$$Revision:--> 64 <!-- $-->, <!--$$JustDate:--> 7/27/01 <!-- $-->
84  */

85 public class AdminApplication implements AdminApp {
86     protected ApplicationConfig mConfig;
87     protected Log mLog;
88     protected TeaServlet mTeaServlet;
89     protected String JavaDoc mAdminKey;
90     protected String JavaDoc mAdminValue;
91     protected AppAdminLinks[] mAdminLinks;
92     // REMOTE stuff
93
TeaServletAdmin mAdmin;
94     String JavaDoc mClusterName;
95     int mRmiPort,mMulticastPort;
96     InetAddress mMulticastGroup;
97     ClusterManager mClusterManager;
98
99     /**
100      * Initializes the Application. Accepts the following initialization
101      * parameters:
102      * <pre>
103      * admin.key - the security parameter key
104      * admin.value - the security parameter value
105      * </pre>
106      *
107      * @param config the application's configuration object
108      */

109     public void init(ApplicationConfig config) {
110         mConfig = config;
111         mLog = config.getLog();
112
113         // Get the admin key/value.
114
mAdminKey = config.getInitParameter("admin.key");
115         mAdminValue = config.getInitParameter("admin.value");
116
117         List serverList = new ArrayList();
118
119         /* OLD CLUSTER stuff
120            // Get the server list.
121            String clusterServers = config.getInitParameter("cluster.servers");
122            if (clusterServers != null) {
123            StringTokenizer st = new StringTokenizer
124            (clusterServers, ",;");
125
126            while (st.hasMoreTokens()) {
127            serverList.add(st.nextToken().trim());
128            }
129
130            if (serverList.isEmpty()) {
131            mLog.warn("No servers specified for this cluster");
132            }
133            }
134
135            mClusteredServers = (String[])serverList.toArray(new String[0]);
136         */

137
138         // Save the TeaServlet reference. The TeaServlet places an instance of
139
// itself in the config in this hidden way because applications don't
140
// need direct access to the TeaServlet.
141
ServletContext JavaDoc context = config.getServletContext();
142         mTeaServlet =
143             (TeaServlet)context.getAttribute(TeaServlet.class.getName());
144         if (mTeaServlet == null) {
145             mLog.warn("TeaServlet attribute not found");
146         }
147         else {
148
149             //REMOTE stuff
150
try {
151                 mAdmin = new TeaServletAdmin(mTeaServlet);
152
153                 String JavaDoc servers = config
154                     .getInitParameter("cluster.servers");
155                 String JavaDoc clusterName = config
156                     .getInitParameter("cluster.name");
157                 int rmiPort = 1099;
158                 int multicastPort = 1099;
159                 InetAddress multicastGroup = null;
160                 String JavaDoc netInterface = config
161                     .getInitParameter("cluster.localNet");
162
163                 try {
164                     rmiPort = Integer.parseInt(config
165                                      .getInitParameter("cluster.rmi.port"));
166                     
167                     multicastPort = Integer.parseInt(config
168                                      .getInitParameter("cluster.multicast.port"));
169
170                     multicastGroup = InetAddress.getByName(config
171                                      .getInitParameter("cluster.multicast.group"));
172                      
173                 }
174                 catch (NumberFormatException JavaDoc nfe) {}
175                 catch (UnknownHostException uhe) {}
176                 if (multicastGroup != null) {
177                     mClusterManager = new ClusterManager(mAdmin,
178                                                          clusterName,
179                                                          null,
180                                                          multicastGroup,
181                                                          multicastPort,
182                                                          rmiPort,
183                                                          netInterface,
184                                                          servers);
185                     mClusterManager.joinCluster();
186                     mClusterManager.launchAuto();
187                 }
188                 else if (servers != null) {
189                     mClusterManager = new ClusterManager(mAdmin,
190                                                          clusterName,
191                                                          null,
192                                                          rmiPort,
193                                                          servers);
194                 }
195                 else {
196                     mLog.debug("No cluster configured.");
197                 }
198             }
199             catch (Exception JavaDoc e) {
200                 mLog.warn(e);
201             }
202         }
203     }
204
205     public void destroy() {
206         if (mClusterManager != null) {
207             mClusterManager.killAuto();
208         }
209     }
210
211     /**
212      * Returns an instance of {@link AdminContext}.
213      */

214     public Object JavaDoc createContext(ApplicationRequest request,
215                                 ApplicationResponse response) {
216         return new ContextImpl(request, response);
217     }
218
219     /**
220      * Returns {@link AdminContext}.class.
221      */

222     public Class JavaDoc getContextType() {
223         return AdminContext.class;
224     }
225
226     void adminCheck(ApplicationRequest request, ApplicationResponse response)
227         throws AbortTemplateException
228     {
229         if (mAdminKey == null) {
230             return;
231         }
232
233         // Check for admin key.
234
String JavaDoc adminParam = request.getParameter(mAdminKey);
235
236         // Look in cookie for admin param.
237
if (adminParam == null) {
238             Cookie JavaDoc[] cookies = request.getCookies();
239             if (cookies != null) {
240                 for (int i = 0; i < cookies.length; i++) {
241                     Cookie JavaDoc cookie = cookies[i];
242                     if (cookie.getName().equals(mAdminKey)) {
243                         adminParam = cookie.getValue();
244                     }
245                 }
246             }
247         }
248
249         if (adminParam != null && adminParam.equals(mAdminValue)) {
250             // Set the admin param in the cookie.
251
Cookie JavaDoc c = new Cookie JavaDoc(mAdminKey, adminParam);
252             // Save cookie for 7 days.
253
c.setMaxAge(24 * 60 * 60 * 7);
254             c.setPath("/");
255             response.addCookie(c);
256         }
257         else {
258             // User is unauthorized.
259

260             mLog.warn("Unauthorized Admin access to " +
261                       request.getRequestURI() +
262                       " from " + request.getRemoteAddr() +
263                       " - " + request.getRemoteHost() +
264                       " - " + request.getRemoteUser());
265
266             try {
267                 response.sendError
268                     (response.SC_NOT_FOUND, request.getRequestURI());
269             }
270             catch (IOException e) {
271             }
272
273             throw new AbortTemplateException();
274         }
275     }
276
277     /**
278      * This implementation uses hard coded link information, but other
279      * applications can dynamically determine their admin links.
280      */

281     public AppAdminLinks getAdminLinks() {
282
283         AppAdminLinks links = new AppAdminLinks(mConfig.getName());
284
285         links.addAdminLink("Templates","/system/teaservlet/AdminTemplates");
286         links.addAdminLink("Functions","/system/teaservlet/AdminFunctions");
287         links.addAdminLink("Applications",
288                            "/system/teaservlet/AdminApplications");
289         links.addAdminLink("Logs","/system/teaservlet/LogViewer");
290         links.addAdminLink("Servlet Engine",
291                            "/system/teaservlet/AdminServletEngine");
292         return links;
293     }
294
295     public class ContextImpl extends TeaToolsUtils implements AdminContext {
296         protected ApplicationRequest mRequest;
297         protected ApplicationResponse mResponse;
298         private TeaServletAdmin mTSAdmin;
299
300         protected ContextImpl(ApplicationRequest request,
301                               ApplicationResponse response) {
302             mRequest = request;
303             mResponse = response;
304         }
305
306         public TeaServletAdmin getTeaServletAdmin() throws ServletException JavaDoc {
307             if (mTSAdmin != null) {
308                 return mTSAdmin;
309             }
310
311             adminCheck(mRequest, mResponse);
312             mTSAdmin = mAdmin;
313             mTSAdmin.setTemplateLoadResult(null);
314             // Cluster related Stuff
315
mTSAdmin.clearServerReloadStatus();
316
317             if (mClusterManager != null) {
318                 mTSAdmin.setClusteredServers(mClusterManager
319                                              .resolveServerNames());
320             }
321             
322             // Admin Link Stuff
323
if (mTSAdmin.getAdminLinks() == null) {
324                 
325                 // add the Teaservlet links first.
326
List links = new ArrayList();
327                 links.add(getAdminLinks());
328
329                 // go through the apps looking for other AdminApps
330
Application[] apps = mTeaServlet
331                     .getApplicationDepot().getApplications();
332                 for (int j = 0;j<apps.length;j++) {
333                     if (apps[j] instanceof AdminApp
334                         && !AdminApplication.this.equals(apps[j])) {
335                         links.add(((AdminApp)apps[j]).getAdminLinks());
336                     }
337                 }
338                 mTSAdmin
339                     .setAdminLinks((AppAdminLinks[])links
340                                    .toArray(new AppAdminLinks[links.size()]));
341             }
342    
343
344             
345
346             // Does the user want to reload templates?
347
String JavaDoc param = mRequest.getParameter("reloadTemplates");
348             if (param != null) {
349                 Boolean JavaDoc all = new Boolean JavaDoc("all".equals(param));
350                 
351                 try {
352                     if (mRequest.getParameter("cluster") != null
353                         && mClusterManager != null) {
354                         clusterReload(mTSAdmin,all);
355                     }
356                     else {
357                         mTSAdmin.restart(all);
358                     }
359                 }
360                 catch (RemoteException JavaDoc re) {
361                     re.printStackTrace();
362                 }
363             }
364
365             // Is the user changing the log settings?
366
param = mRequest.getParameter("log");
367             if (param != null) {
368                 Log log;
369                 try {
370                     log = (Log)ObjectIdentifier.retrieve(param);
371                 }
372                 catch (ClassCastException JavaDoc e) {
373                     log = null;
374                 }
375
376                 if (log != null) {
377                     String JavaDoc setting = mRequest.getParameter("enabled");
378                     if (setting != null) {
379                         log.setEnabled(setting.equals("true"));
380                     }
381                     setting = mRequest.getParameter("debug");
382                     if (setting != null) {
383                         log.setDebugEnabled(setting.equals("true"));
384                     }
385                     setting = mRequest.getParameter("info");
386                     if (setting != null) {
387                         log.setInfoEnabled(setting.equals("true"));
388                     }
389                     setting = mRequest.getParameter("warn");
390                     if (setting != null) {
391                         log.setWarnEnabled(setting.equals("true"));
392                     }
393                     setting = mRequest.getParameter("error");
394                     if (setting != null) {
395                         log.setErrorEnabled(setting.equals("true"));
396                     }
397                 }
398
399                 try {
400                     mResponse.sendRedirect(mRequest.getRequestURI());
401                     throw new AbortTemplateException();
402                 }
403                 catch (IOException e) {
404                 }
405             }
406
407             return mTSAdmin;
408         }
409
410         public String JavaDoc getObjectIdentifier(Object JavaDoc obj) {
411             return ObjectIdentifier.identify(obj);
412         }
413
414         public Class JavaDoc getClassForName(String JavaDoc classname) {
415             try {
416                 ClassLoader JavaDoc cl = mTeaServlet.getApplicationDepot()
417                     .getContextType().getClassLoader();
418                 if (cl == null) {
419                     cl = ClassLoader.getSystemClassLoader();
420                 }
421                 return cl.loadClass(classname);
422             }
423             catch (Exception JavaDoc cpe) {
424                 mLog.warn(cpe);
425                 return null;
426             }
427         }
428
429         /**
430          * Streams the structural bytes of the named class via the
431          * HttpResponse.
432          */

433         public void streamClassBytes(String JavaDoc className)
434             throws AbortTemplateException
435         {
436             adminCheck(mRequest, mResponse);
437
438             mLog.debug("streamClassBytes: " + className);
439
440             if (className == null) {
441                 return;
442             }
443
444             String JavaDoc classResource = className.replace('.', '/') + ".class";
445
446             ClassLoader JavaDoc cl = mTeaServlet.getApplicationDepot().getContextType()
447                 .getClassLoader();
448             if (cl == null) {
449                 cl = ClassLoader.getSystemClassLoader();
450             }
451            
452             InputStream in = cl.getResourceAsStream(classResource);
453
454             if (in != null) {
455                 mLog.debug("streamClassBytes: Got InputStream for class: " +
456                            className);
457
458                 int len = 4000;
459                 byte[] b = new byte[len];
460                 int bytesRead = 0;
461                 ByteBuffer buffer = mResponse.getResponseBuffer();
462                 
463                 try {
464                     while ((bytesRead = in.read(b, 0, len)) > 0) {
465                         buffer.append(b, 0, bytesRead);
466                     }
467         
468                     in.close();
469                 }
470                 catch (Exception JavaDoc e) {
471                     mResponse.setStatus(mResponse.SC_NOT_FOUND);
472                     mLog.debug(e);
473                 }
474             }
475             else {
476                 mResponse.setStatus(mResponse.SC_NOT_FOUND);
477             }
478
479             mResponse.setContentType("application/java");
480         }
481
482
483         /**
484          * allows a template to dynamically call another template
485          */

486         public void dynamicTemplateCall(String JavaDoc templateName)
487             throws Exception JavaDoc {
488             dynamicTemplateCall(templateName,new Object JavaDoc[0]);
489         }
490
491         /**
492          * allows a template to dynamically call another template
493          * this time with parameters.
494          */

495         public void dynamicTemplateCall(String JavaDoc templateName, Object JavaDoc[] params)
496             throws Exception JavaDoc
497         {
498             com.go.tea.runtime.Context context = mResponse
499                 .getHttpContext();
500             com.go.tea.runtime.TemplateLoader.Template td =
501                 mTeaServlet.getApplicationDepot()
502                 .getTemplateDepot().findTemplate(templateName,
503                                                  mRequest,
504                                                  mResponse);
505
506             // make sure we have the right number and types of parameters
507
String JavaDoc[] paramNames = td.getParameterNames();
508             Object JavaDoc[] oldParams = params;
509             if (oldParams == null
510                 || oldParams.length != paramNames.length) {
511                 params = new Object JavaDoc[paramNames.length];
512                 
513                 /*
514                  * if the provided parameters don't match up with the
515                  * required parameters first try to fill in the params
516                  * from the request then fill the rest with nulls.
517                  * NOTE: if the parameters explicitly passed in do not
518                  * match the template signature, none of those parameters
519                  * will be used
520                  */

521
522                 for (int j=0;j<paramNames.length;j++) {
523                     params[j] = mRequest.getParameter(paramNames[j]);
524                     if (params[j] == null && oldParams.length > j) {
525                         params[j] = oldParams[j];
526                     }
527                 }
528             }
529
530             td.execute(context, params);
531         }
532     
533         public Object JavaDoc obtainContextByName(String JavaDoc appName)
534             throws ServletException JavaDoc {
535             ApplicationInfo[] applications =
536                 getTeaServletAdmin().getApplications();
537             for (int j=0;j<applications.length;j++) {
538                 if (appName.equals(applications[j].getName())) {
539                     return ((Application)applications[j].getValue())
540                         .createContext(mRequest,mResponse);
541                 }
542             }
543             return null;
544         }
545
546         /* not currently used. TODO: delete these when sure we won't use again
547         
548         public FeatureDescription[] sort(FeatureDescription[] fds) {
549             return sortDescriptions(fds);
550         }
551
552         public FeatureDescriptor[] sort(FeatureDescriptor[] fds) {
553             return sortDescriptors(fds);
554         }
555
556         public Object[] sort(Object[] objArray) {
557             Object[] dolly = (Object[])objArray.clone();
558             Arrays.sort(dolly);
559             return dolly;
560         }
561
562         public PropertyDescriptor[] getBeanProperties(Class beanClass)
563             throws IntrospectionException
564         {
565             if (beanClass == null) {
566                 return null;
567             }
568
569             PropertyDescriptor[] pdarray = new PropertyDescriptor[0];
570
571             Collection props =
572                 BeanAnalyzer.getAllProperties(beanClass).values();
573             pdarray = (PropertyDescriptor[])props.toArray(pdarray);
574             Comparator pdcomp = BeanComparator
575                 .forClass(PropertyDescriptor.class).orderBy("name");
576             java.util.Arrays.sort(pdarray, pdcomp);
577
578             return pdarray;
579         }
580         */

581
582         private void clusterReload(TeaServletAdmin admin, Boolean JavaDoc all)
583             throws RemoteException JavaDoc {
584             
585             /* OLD Cluster Stuff
586                StringBuffer uri = new StringBuffer();
587
588                uri.append(mRequest.getContextPath());
589                uri.append(mRequest.getServletPath());
590                uri.append("/system/teaservlet/ClusterReload?reloadTemplates");
591
592                if (all) {
593                uri.append("=all");
594                }
595
596                if (mAdminKey != null && mAdminValue != null) {
597                uri.append('&');
598                uri.append(mAdminKey);
599                uri.append('=');
600                uri.append(mAdminValue);
601                }
602
603                int port = mRequest.getServerPort();
604             */

605             if (mClusterManager != null) {
606
607                 mClusterManager.resolveServerNames();
608
609                 Clustered[] peers =
610                     (Clustered[])mClusterManager.getCluster()
611                     .getKnownPeers();
612
613                 final ClusterThread[] ct = new ClusterThread[peers.length];
614
615                 for (int i=0; i<peers.length; i++) {
616                     Clustered peer = peers[i];
617                     ct[i] = new ClusterThread(admin, peer, all);
618                     ct[i].start();
619                 
620                 }
621             
622                 Thread JavaDoc monitor = new Thread JavaDoc("Template reload monitor") {
623                         public void run() {
624                             for (int i=0; i<ct.length; i++) {
625                                 if (ct[i] != null) {
626                                     try {
627                                         ct[i].join();
628                                     }
629                                     catch (InterruptedException JavaDoc e) {
630                                         break;
631                                     }
632                                 }
633                             }
634                         }
635                     };
636
637                 monitor.start();
638                 try {
639                     // Wait at most 30 seconds for all servers to respond.
640
monitor.join(30000);
641                 }
642                 catch (InterruptedException JavaDoc e) {
643                 }
644
645                 monitor.interrupt();
646
647                 for (int i=0; i<ct.length; i++) {
648                     if (ct[i] != null) {
649                         ct[i].interrupt();
650                     }
651                 }
652             }
653         }
654         
655         public TeaToolsContext.HandyClassInfo getHandyClassInfo(String JavaDoc fullClassName) {
656             if (fullClassName != null) {
657                 Class JavaDoc clazz = getClassForName(fullClassName);
658                 if (clazz != null) {
659                     return getHandyClassInfo(clazz);
660                 }
661             }
662             return null;
663         }
664         
665         public TeaToolsContext.HandyClassInfo getHandyClassInfo(Class JavaDoc clazz) {
666             if (clazz != null) {
667                 return new HandyClassInfoImpl(clazz);
668             }
669             return null;
670         }
671         
672         public class HandyClassInfoImpl extends TypeDescription
673             implements TeaToolsContext.HandyClassInfo
674         {
675             
676             HandyClassInfoImpl(Class JavaDoc clazz) {
677                 super(clazz,ContextImpl.this);
678             }
679         }
680     }
681     
682     private class ClusterThread extends Thread JavaDoc {
683         private TeaServletAdmin mTSAdmin;
684         private Clustered mClusterPeer;
685         private Boolean JavaDoc mAll;
686
687         public ClusterThread(TeaServletAdmin admin,
688                              Clustered peer,
689                              Boolean JavaDoc all) {
690             mTSAdmin = admin;
691             mClusterPeer = peer;
692             mAll = all;
693
694         }
695
696         public void run() {
697             try {
698                 try {
699                     ((Restartable)mClusterPeer).restart(mAll);
700                     mTSAdmin.setServerReloadStatus(mClusterPeer
701                                                    .getServerName(),
702                                                    200,
703                                                    ((Restartable)mClusterPeer)
704                                                    .getStatus(mAll));
705                 }
706                 catch (IOException e) {
707                     e.printStackTrace();
708                     mTSAdmin.setServerReloadStatus
709                         (mClusterPeer.getServerName(),500, e.toString());
710                 }
711             }
712             catch (RemoteException JavaDoc re) {
713                 try {
714                     mClusterManager.getCluster().removePeer(mClusterPeer);
715                 }
716                 catch (RemoteException JavaDoc re2) {
717                     re2.printStackTrace();
718                 }
719                 mTSAdmin.setServerReloadStatus
720                     ("N/A",500, "Unknown host");
721             }
722         }
723     }
724 }
725
Popular Tags