1. 程式人生 > >tomcat原始碼淺析(三)之webapps的解析

tomcat原始碼淺析(三)之webapps的解析

1.HostConfig在start中會呼叫deployApps方法掃描appBase目錄下的apps,載入DocBase/META-INF/context.xml.

Hostconfig.deployapps程式碼
  1. protected void deployApps() {  
  2.   
  3.         File appBase = appBase();  
  4.         File configBase = configBase();  
  5.         String[] filteredAppPaths = filterAppPaths(appBase.list());  
  6.         // Deploy XML descriptors from configBase  
  7.         deployDescriptors(configBase, configBase.list());  
  8.         // Deploy WARs  
  9.         deployWARs(appBase, filteredAppPaths);  
  10.         // Deploy expanded folders  
  11.         deployDirectories(appBase, filteredAppPaths);  
  12.   
  13.     }  

 

Hostconfig.deploydescriptor程式碼
  1. protected void deployDescriptor(ContextName cn, File contextXml) {  
  2.   
  3.         DeployedApplication deployedApp =  
  4.                 new DeployedApplication(cn.getName(), true);  
  5.   
  6.         long startTime = 0;  
  7.         // Assume this is a configuration descriptor and deploy it  
  8.         if(log.isInfoEnabled()) {  
  9.            startTime = System.currentTimeMillis();  
  10.            log.info(sm.getString("hostConfig.deployDescriptor",  
  11.                     contextXml.getAbsolutePath()));  
  12.         }  
  13.   
  14.         Context context = null;  
  15.         boolean isExternalWar = false;  
  16.         boolean isExternal = false;  
  17.         File expandedDocBase = null;  
  18.         FileInputStream fis = null;  
  19.         try {  
  20.             fis = new FileInputStream(contextXml);  
  21.             synchronized (digesterLock) {  
  22.                 try {  
  23.                     context = (Context) digester.parse(fis);  
  24.                 } catch (Exception e) {  
  25.                     log.error(sm.getString(  
  26.                             "hostConfig.deployDescriptor.error",  
  27.                             contextXml.getAbsolutePath()), e);  
  28.                     context = new FailedContext();  
  29.                 } finally {  
  30.                     digester.reset();  
  31.                 }  
  32.             }  
  33.   
  34.             Class<?> clazz = Class.forName(host.getConfigClass());  
  35.             LifecycleListener listener =  
  36.                 (LifecycleListener) clazz.newInstance();  
  37.             context.addLifecycleListener(listener);  
  38.   
  39.             context.setConfigFile(contextXml.toURI().toURL());  
  40.             context.setName(cn.getName());  
  41.             context.setPath(cn.getPath());  
  42.             context.setWebappVersion(cn.getVersion());  
  43.             // Add the associated docBase to the redeployed list if it's a WAR  
  44.             if (context.getDocBase() != null) {  
  45.                 File docBase = new File(context.getDocBase());  
  46.                 if (!docBase.isAbsolute()) {  
  47.                     docBase = new File(appBase(), context.getDocBase());  
  48.                 }  
  49.                 // If external docBase, register .xml as redeploy first  
  50.                 if (!docBase.getCanonicalPath().startsWith(  
  51.                         appBase().getAbsolutePath() + File.separator)) {  
  52.                     isExternal = true;  
  53.                     deployedApp.redeployResources.put(  
  54.                             contextXml.getAbsolutePath(),  
  55.                             Long.valueOf(contextXml.lastModified()));  
  56.                     deployedApp.redeployResources.put(docBase.getAbsolutePath(),  
  57.                             Long.valueOf(docBase.lastModified()));  
  58.                     if (docBase.getAbsolutePath().toLowerCase(Locale.ENGLISH).endsWith(".war")) {  
  59.                         isExternalWar = true;  
  60.                     }  
  61.                 } else {  
  62.                     log.warn(sm.getString("hostConfig.deployDescriptor.localDocBaseSpecified",  
  63.                              docBase));  
  64.                     // Ignore specified docBase  
  65.                     context.setDocBase(null);  
  66.                 }  
  67.             }  
  68.   
  69.             host.addChild(context);  
  70.         } catch (Throwable t) {  
  71.             ExceptionUtils.handleThrowable(t);  
  72.             log.error(sm.getString("hostConfig.deployDescriptor.error",  
  73.                                    contextXml.getAbsolutePath()), t);  
  74.         } finally {  
  75.             if (fis != null) {  
  76.                 try {  
  77.                     fis.close();  
  78.                 } catch (IOException e) {  
  79.                     // Ignore  
  80.                 }  
  81.             }  
  82.             // Get paths for WAR and expanded WAR in appBase  
  83.   
  84.             // default to appBase dir + name  
  85.             expandedDocBase = new File(appBase(), cn.getBaseName());  
  86.             if (context.getDocBase() != null  
  87.                     && !context.getDocBase().toLowerCase(Locale.ENGLISH).endsWith(".war")) {  
  88.                 // first assume docBase is absolute  
  89.                 expandedDocBase = new File(context.getDocBase());  
  90.                 if (!expandedDocBase.isAbsolute()) {  
  91.                     // if docBase specified and relative, it must be relative to appBase  
  92.                     expandedDocBase = new File(appBase(), context.getDocBase());  
  93.                 }  
  94.             }  
  95.   
  96.             boolean unpackWAR = unpackWARs;  
  97.             if (unpackWAR && context instanceof StandardContext) {  
  98.                 unpackWAR = ((StandardContext) context).getUnpackWAR();  
  99.             }  
  100.   
  101.             // Add the eventual unpacked WAR and all the resources which will be  
  102.             // watched inside it  
  103.             if (isExternalWar) {  
  104.                 if (unpackWAR) {  
  105.                     deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(),  
  106.                             Long.valueOf(expandedDocBase.lastModified()));  
  107.                     addWatchedResources(deployedApp, expandedDocBase.getAbsolutePath(), context);  
  108.                 } else {  
  109.                     addWatchedResources(deployedApp, null, context);  
  110.                 }  
  111.             } else {  
  112.                 // Find an existing matching war and expanded folder  
  113.                 if (!isExternal) {  
  114.                     File warDocBase = new File(expandedDocBase.getAbsolutePath() + ".war");  
  115.                     if (warDocBase.exists()) {  
  116.                         deployedApp.redeployResources.put(warDocBase.getAbsolutePath(),  
  117.                                 Long.valueOf(warDocBase.lastModified()));  
  118.                     } else {  
  119.                         // Trigger a redeploy if a WAR is added  
  120.                         deployedApp.redeployResources.put(  
  121.                                 warDocBase.getAbsolutePath(),  
  122.                                 Long.valueOf(0));  
  123.                     }  
  124.                 }  
  125.                 if (unpackWAR) {  
  126.                     deployedApp.redeployResources.put(expandedDocBase.getAbsolutePath(),  
  127.                             Long.valueOf(expandedDocBase.lastModified()));  
  128.                     addWatchedResources(deployedApp,  
  129.                             expandedDocBase.getAbsolutePath(), context);  
  130.                 } else {  
  131.                     addWatchedResources(deployedApp, null, context);  
  132.                 }  
  133.                 if (!isExternal) {  
  134.                     // For external docBases, the context.xml will have been  
  135.                     // added above.  
  136.                     deployedApp.redeployResources.put(  
  137.                             contextXml.getAbsolutePath(),  
  138.                             Long.valueOf(contextXml.lastModified()));  
  139.                 }  
  140.             }  
  141.             // Add the global redeploy resources (which are never deleted) at  
  142.             // the end so they don't interfere with the deletion process  
  143.             addGlobalRedeployResources(deployedApp);  
  144.         }  
  145.   
  146.         if (host.findChild(context.getName()) != null) {  
  147.             deployed.put(context.getName(), deployedApp);  
  148.         }  
  149.   
  150.         if (log.isInfoEnabled()) {  
  151.             log.info(sm.getString("hostConfig.deployDescriptor.finished",  
  152.                 contextXml.getAbsolutePath(), Long.valueOf(System.currentTimeMillis() - startTime)));  
  153.         }  
  154.     }  

 

Hostconfig.deploywar程式碼
  1. protected void deployWAR(ContextName cn, File war) {  
  2.   
  3.        // Checking for a nested /META-INF/context.xml  
  4.        JarFile jar = null;  
  5.        InputStream istream = null;  
  6.        FileOutputStream fos = null;  
  7.        BufferedOutputStream ostream = null;  
  8.   
  9.        File xml = new File(appBase(),  
  10.                cn.getBaseName() + "/META-INF/context.xml");  
  11.   
  12.        boolean xmlInWar = false;  
  13.        try {  
  14.            jar = new JarFile(war);  
  15.            JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);  
  16.            if (entry != null) {  
  17.                xmlInWar = true;  
  18.            }  
  19.        } catch (IOException e) {  
  20.            /* Ignore */  
  21.        } finally {  
  22.            if (jar != null) {  
  23.                try {  
  24.                    jar.close();  
  25.                } catch (IOException ioe) {  
  26.                    // Ignore;  
  27.                }  
  28.                jar = null;  
  29.            }  
  30.        }  
  31.   
  32.        Context context = null;  
  33.        try {  
  34.            if (deployXML && xml.exists() && unpackWARs && !copyXML) {  
  35.                synchronized (digesterLock) {  
  36.                    try {  
  37.                        context = (Context) digester.parse(xml);  
  38.                    } catch (Exception e) {  
  39.                        log.error(sm.getString(  
  40.                                "hostConfig.deployDescriptor.error",  
  41.                                war.getAbsolutePath()), e);  
  42.                    } finally {  
  43.                        digester.reset();  
  44.                        if (context == null) {  
  45.                            context = new FailedContext();  
  46.                        }  
  47.                    }  
  48.                }  
  49.                context.setConfigFile(xml.toURI().toURL());  
  50.            } else if (deployXML && xmlInWar) {  
  51.                synchronized (digesterLock) {  
  52.                    try {  
  53.                        jar = new JarFile(war);  
  54.                        JarEntry entry =  
  55.                            jar.getJarEntry(Constants.ApplicationContextXml);  
  56.                        istream = jar.getInputStream(entry);  
  57.                        context = (Context) digester.parse(istream);  
  58.                    } catch (Exception e) {  
  59.                        log.error(sm.getString(  
  60.                                "hostConfig.deployDescriptor.error",  
  61.                                war.getAbsolutePath()), e);  
  62.                    } finally {  
  63.                        digester.reset();  
  64.                        if (istream != null) {  
  65.                            try {  
  66.                                istream.close();  
  67.                            } catch (IOException e) {  
  68.                                /* Ignore */  
  69.                            }  
  70.                            istream = null;  
  71.                        }  
  72.                        if (jar != null) {  
  73.                            try {  
  74.                                jar.close();  
  75.                            } catch (IOException e) {  
  76.                                /* Ignore */  
  77.                            }  
  78.                            jar = null;  
  79.                        }  
  80.                        if (context == null) {  
  81.                            context = new FailedContext();  
  82.                        }  
  83.                        context.setConfigFile(  
  84.                                UriUtil.buildJarUrl(war, Constants.ApplicationContextXml));  
  85.                    }  
  86.                }  
  87.            } else if (!deployXML && xmlInWar) {  
  88.                // Block deployment as META-INF/context.xml may contain security  
  89.                // configuration necessary for a secure deployment.  
  90.                log.error(sm.getString("hostConfig.deployDescriptor.blocked",  
  91.                        cn.getPath(), Constants.ApplicationContextXml,  
  92.                        new File(configBase(), cn.getBaseName() + ".xml")));  
  93.            } else {  
  94.                context = (Context) Class.forName(contextClass).newInstance();  
  95.            }  
  96.        } catch (Throwable t) {  
  97.            ExceptionUtils.handleThrowable(t);  
  98.            log.error(sm.getString("hostConfig.deployWar.error",  
  99.                    war.getAbsolutePath()), t);  
  100.        } finally {  
  101.            if (context == null) {  
  102.                context = new FailedContext();  
  103.            }  
  104.        }  
  105.   
  106.        boolean copyThisXml = false;  
  107.        if (deployXML) {  
  108.            if (host instanceof StandardHost) {  
  109.                copyThisXml = ((StandardHost) host).isCopyXML();  
  110.            }  
  111.   
  112.            // If Host is using default value Context can override it.  
  113.            if (!copyThisXml && context instanceof StandardContext) {  
  114.                copyThisXml = ((StandardContext) context).getCopyXML();  
  115.            }  
  116.   
  117.            if (xmlInWar && copyThisXml) {  
  118.                // Change location of XML file to config base  
  119.                xml = new File(configBase(), cn.getBaseName() + ".xml");  
  120.                try {  
  121.                    jar = new JarFile(war);  
  122.                    JarEntry entry =  
  123.                        jar.getJarEntry(Constants.ApplicationContextXml);  
  124.                    istream = jar.getInputStream(entry);  
  125.   
  126.                    fos = new FileOutputStream(xml);  
  127.                    ostream = new BufferedOutputStream(fos, 1024);  
  128.                    byte buffer[] = new byte[1024];  
  129.                    while (true) {  
  130.                        int n = istream.read(buffer);  
  131.                        if (n < 0) {  
  132.                            break;  
  133.                        }  
  134.                        ostream.write(buffer, 0, n);  
  135.                    }  
  136.                    ostream.flush();  
  137.                } catch (IOException e) {  
  138.                    /* Ignore */  
  139.                } finally {  
  140.                    if (ostream != null) {  
  141.                        try {  
  142.                            ostream.close();  
  143.                        } catch (IOException ioe) {  
  144.                            // Ignore  
  145.                        }  
  146.                        ostream = null;  
  147.                    }  
  148.                    if (fos != null) {  
  149.                        try {  
  150.                            fos.close();  
  151.                        } catch (IOException ioe) {  
  152.                            // Ignore  
  153.                        }  
  154.                        fos = null;  
  155.                    }  
  156.                    if (istream != null) {  
  157.                        try {  
  158.                            istream.close();  
  159.                        } catch (IOException ioe) {  
  160.                            // Ignore  
  161.                        }  
  162.                        istream = null;  
  163.                    }  
  164.                    if (jar != null) {  
  165.                        try {  
  166.                            jar.close();  
  167.                        } catch (IOException ioe) {  
  168.                            // Ignore;  
  169.                        }  
  170.                        jar = null;  
  171.                    }  
  172.                }  
  173.            }  
  174.        }  
  175.   
  176.        DeployedApplication deployedApp = new DeployedApplication(cn.getName(),  
  177.                xml.exists() && deployXML && copyThisXml);  
  178.   
  179.        long startTime = 0;  
  180.        // Deploy the application in this WAR file  
  181.        if(log.isInfoEnabled()) {  
  182.            startTime = System.currentTimeMillis();  
  183.            log.info(sm.getString("hostConfig.deployWar",  
  184.                    war.getAbsolutePath()));  
  185.        }  
  186.   
  187.        try {  
  188.            // Populate redeploy resources with the WAR file  
  189.            deployedApp.redeployResources.put  
  190.                (war.getAbsolutePath(), Long.valueOf(war.lastModified()));  
  191.   
  192.            if (deployXML && xml.exists() && copyThisXml) {  
  193.                deployedApp.redeployResources.put(xml.getAbsolutePath(),  
  194.                        Long.valueOf(xml.lastModified()));  
  195.            } else {  
  196.                // In case an XML file is added to the config base later  
  197.                deployedApp.redeployResources.put(  
  198.                        (new File(configBase(),  
  199.                                cn.getBaseName() + ".xml")).getAbsolutePath(),  
  200.                        Long.valueOf(0));  
  201.            }  
  202.   
  203.            Class<?> clazz = Class.forName(host.getConfigClass());  
  204.            LifecycleListener listener =  
  205.                (LifecycleListener) clazz.newInstance();  
  206.            context.addLifecycleListener(listener);  
  207.   
  208.            context.setName(cn.getName());  
  209.            context.setPath(cn.getPath());  
  210.            context.setWebappVersion(cn.getVersion());  
  211.            context.setDocBase(cn.getBaseName() + ".war");  
  212.            host.addChild(context);  
  213.        } catch (Throwable t) {  
  214.            ExceptionUtils.handleThrowable(t);  
  215.            log.error(sm.getString("hostConfig.deployWar.error",  
  216.                    war.getAbsolutePath()), t);  
  217.        } finally {  
  218.            // If we're unpacking WARs, the&nbs