zoukankan      html  css  js  c++  java
  • context创建过程解析(二)之deployWARs

    HostConfig.deployApps()
    //在监听到start事件类型,也就是StandardHost调用startInternal
    protected void deployApps() {
    
            File appBase = host.getAppBaseFile();
    //这个值是在触发before_start时间时生成的,默认是tomcat安装目录+engine名+host名
            File configBase = host.getConfigBaseFile();
    //获取host上配置的webapp下的所有文件,默认是webapps目录下的所有文件
            String[] filteredAppPaths = filterAppPaths(appBase.list());
            // Deploy XML descriptors from configBase  发布xml描述文件
            deployDescriptors(configBase, configBase.list());
            // Deploy WARs
            deployWARs(appBase, filteredAppPaths);
            // Deploy expanded folders
            deployDirectories(appBase, filteredAppPaths);
    
        }
    
    deployWARs
    
    protected void deployWARs(File appBase, String[] files) {
    
            if (files == null)
                return;
    
            ExecutorService es = host.getStartStopExecutor();
            List<Future<?>> results = new ArrayList<>();
    
            for (int i = 0; i < files.length; i++) {
    
                if (files[i].equalsIgnoreCase("META-INF"))
                    continue;
                if (files[i].equalsIgnoreCase("WEB-INF"))
                    continue;
                File war = new File(appBase, files[i]);
    //处理war
                if (files[i].toLowerCase(Locale.ENGLISH).endsWith(".war") &&
                        war.isFile() && !invalidWars.contains(files[i]) ) {
    
                    ContextName cn = new ContextName(files[i], true);
    
                    if (isServiced(cn.getName())) {
                        continue;
                    }
    //如果已经发布
                    if (deploymentExists(cn.getName())) {
                        DeployedApplication app = deployed.get(cn.getName());
                        boolean unpackWAR = unpackWARs;
                        if (unpackWAR && host.findChild(cn.getName()) instanceof StandardContext) {
                            unpackWAR = ((StandardContext) host.findChild(cn.getName())).getUnpackWAR();
                        }
    //如果不需要解压,并且已经发布。那么判断对应的docBase是否已经存在
                        if (!unpackWAR && app != null) {
                            // Need to check for a directory that should not be
                            // there
                            File dir = new File(appBase, cn.getBaseName());
                            if (dir.exists()) {
                                if (!app.loggedDirWarning) {
                                    log.warn(sm.getString(
                                            "hostConfig.deployWar.hiddenDir",
                                            dir.getAbsoluteFile(),
                                            war.getAbsoluteFile()));
                                    app.loggedDirWarning = true;
                                }
                            } else {
                                app.loggedDirWarning = false;
                            }
                        }
                        continue;
                    }
    
                    // Check for WARs with /../ /./ or similar sequences in the name
                    if (!validateContextPath(appBase, cn.getBaseName())) {
                        log.error(sm.getString(
                                "hostConfig.illegalWarName", files[i]));
                        invalidWars.add(files[i]);
                        continue;
                    }
    
                    results.add(es.submit(new DeployWar(this, cn, war)));
                }
            }
    
            for (Future<?> result : results) {
                try {
                    result.get();
                } catch (Exception e) {
                    log.error(sm.getString(
                            "hostConfig.deployWar.threaded.error"), e);
                }
            }
        }
    
    
    HostConfig.deployWAR(cn, war);
    
    protected void deployWAR(ContextName cn, File war) {
    
    // Constants.ApplicationContextXml == META-INF/context.xml
            File xml = new File(host.getAppBaseFile(),
                    cn.getBaseName() + "/" + Constants.ApplicationContextXml);
    
            File warTracker = new File(host.getAppBaseFile(), cn.getBaseName() + Constants.WarTracker);
    
            boolean xmlInWar = false;
            try (JarFile jar = new JarFile(war)) {
                JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
    //判断是否有context.xml在jar包里面
                if (entry != null) {
                    xmlInWar = true;
                }
            } catch (IOException e) {
                /* Ignore */
            }
    
            // If there is an expanded directory then any xml in that directory
            // should only be used if the directory is not out of date and
            // unpackWARs is true. Note the code below may apply further limits
            boolean useXml = false;
            // If the xml file exists then expandedDir must exists so no need to
            // test that here
    //如果对应xml存在,并且允许解压,也就是已经解压了,这个war包没有修改过
            if (xml.exists() && unpackWARs &&
                    (!warTracker.exists() || warTracker.lastModified() == war.lastModified())) {
                useXml = true;
            }
    
            Context context = null;
    //是否需要发布这个context.xml,通过校验
            boolean deployThisXML = isDeployThisXML(war, cn);
    
            try {
    //允许发布这个xml并且仅仅是使用xml并且不允许copyxml到配置目录,如果允许copy到配置目录,那么这个xml可能不是最新的。
                if (deployThisXML && useXml && !copyXML) {
                    synchronized (digesterLock) {
                        try {
                            context = (Context) digester.parse(xml);
                        } catch (Exception e) {
                            log.error(sm.getString(
                                    "hostConfig.deployDescriptor.error",
                                    war.getAbsolutePath()), e);
                        } finally {
                            digester.reset();
                            if (context == null) {
                                context = new FailedContext();
                            }
                        }
                    }
    //设置context.xml配置文件
                    context.setConfigFile(xml.toURI().toURL());
    //允许发布这个context.xml并且这个xml在war包里面
                } else if (deployThisXML && xmlInWar) {
                    synchronized (digesterLock) {
                        try (JarFile jar = new JarFile(war)) {
                            JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
                            try (InputStream istream = jar.getInputStream(entry)) {
                                context = (Context) digester.parse(istream);
                            }
                        } catch (Exception e) {
                            log.error(sm.getString(
                                    "hostConfig.deployDescriptor.error",
                                    war.getAbsolutePath()), e);
                        } finally {
                            digester.reset();
                            if (context == null) {
                                context = new FailedContext();
                            }
                            context.setConfigFile(
                                    UriUtil.buildJarUrl(war, Constants.ApplicationContextXml));
                        }
                    }
    //不允许发布这个context.xml并且这个xml在war包里面的,那么就直接new出一个StandardContext
                } else if (!deployThisXML && xmlInWar) {
                    // Block deployment as META-INF/context.xml may contain security
                    // configuration necessary for a secure deployment.
                    log.error(sm.getString("hostConfig.deployDescriptor.blocked",
                            cn.getPath(), Constants.ApplicationContextXml,
                            new File(host.getConfigBaseFile(), cn.getBaseName() + ".xml")));
                } else {
                    context = (Context) Class.forName(contextClass).getConstructor().newInstance();
                }
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("hostConfig.deployWar.error",
                        war.getAbsolutePath()), t);
            } finally {
                if (context == null) {
                    context = new FailedContext();
                }
            }
    
            boolean copyThisXml = false;//是否需要复制xml到配置文件夹中
            if (deployThisXML) {//允许发布
                if (host instanceof StandardHost) {
                    copyThisXml = ((StandardHost) host).isCopyXML();
                }
    
                // If Host is using default value Context can override it. context指定的copyXml属性可以覆盖host级别的
                if (!copyThisXml && context instanceof StandardContext) {
                    copyThisXml = ((StandardContext) context).getCopyXML();
                }
    //如果context.xml在war中,并且允许复制这个xml到配置路径,那么就将此context.xml复制到配置文件夹中
                if (xmlInWar && copyThisXml) {
                    // Change location of XML file to config base
                    xml = new File(host.getConfigBaseFile(),
                            cn.getBaseName() + ".xml");
                    try (JarFile jar = new JarFile(war)) {
                        JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
                        try (InputStream istream = jar.getInputStream(entry);
                                FileOutputStream fos = new FileOutputStream(xml);
                                BufferedOutputStream ostream = new BufferedOutputStream(fos, 1024)) {
                            byte buffer[] = new byte[1024];
                            while (true) {
                                int n = istream.read(buffer);
                                if (n < 0) {
                                    break;
                                }
                                ostream.write(buffer, 0, n);
                            }
                            ostream.flush();
                        }
                    } catch (IOException e) {
                        /* Ignore */
                    }
                }
            }
    //下面这部分代码基本和deployDescriptors差不多
            DeployedApplication deployedApp = new DeployedApplication(cn.getName(),
                    xml.exists() && deployThisXML && copyThisXml);
    
            long startTime = 0;
            // Deploy the application in this WAR file
            if(log.isInfoEnabled()) {
                startTime = System.currentTimeMillis();
                log.info(sm.getString("hostConfig.deployWar",
                        war.getAbsolutePath()));
            }
    
            try {
                // Populate redeploy resources with the WAR file
                deployedApp.redeployResources.put
                    (war.getAbsolutePath(), Long.valueOf(war.lastModified()));
    
                if (deployThisXML && xml.exists() && copyThisXml) {
    //这个xml被复制到配置目录
                    deployedApp.redeployResources.put(xml.getAbsolutePath(),
                            Long.valueOf(xml.lastModified()));
                } else {
                    // In case an XML file is added to the config base later 如果配置加载配置目录中才会有效
                    deployedApp.redeployResources.put(
                            (new File(host.getConfigBaseFile(),
                                    cn.getBaseName() + ".xml")).getAbsolutePath(),
                            Long.valueOf(0));
                }
    
                Class<?> clazz = Class.forName(host.getConfigClass());
                LifecycleListener listener = (LifecycleListener) clazz.getConstructor().newInstance();
                context.addLifecycleListener(listener);
    
                context.setName(cn.getName());
                context.setPath(cn.getPath());
                context.setWebappVersion(cn.getVersion());
                context.setDocBase(cn.getBaseName() + ".war");
         host.addChild(context);//与deployDescriptors一样的操作
            } catch (Throwable t) {
                ExceptionUtils.handleThrowable(t);
                log.error(sm.getString("hostConfig.deployWar.error",
                        war.getAbsolutePath()), t);
            } finally {
                // If we're unpacking WARs, the docBase will be mutated after
                // starting the context
                boolean unpackWAR = unpackWARs;
                if (unpackWAR && context instanceof StandardContext) {
                    unpackWAR = ((StandardContext) context).getUnpackWAR();
                }
    //上面不是已经添加了docBase资源的监控了吗?这里是因为tomcat在解压了war之后会重新定义它的docBase目录,所以需要添加,不管原始的还是新的都要进行监控
                if (unpackWAR && context.getDocBase() != null) {
                    File docBase = new File(host.getAppBaseFile(), cn.getBaseName());
                    deployedApp.redeployResources.put(docBase.getAbsolutePath(),
                            Long.valueOf(docBase.lastModified()));
                    addWatchedResources(deployedApp, docBase.getAbsolutePath(),
                            context);
                    if (deployThisXML && !copyThisXml && (xmlInWar || xml.exists())) {
                        deployedApp.redeployResources.put(xml.getAbsolutePath(),
                                Long.valueOf(xml.lastModified()));
                    }
                } else {
                    // Passing null for docBase means that no resources will be
                    // watched. This will be logged at debug level.
                    addWatchedResources(deployedApp, null, context);
                }
                // Add the global redeploy resources (which are never deleted) at
                // the end so they don't interfere with the deletion process
                addGlobalRedeployResources(deployedApp);
            }
    
            deployed.put(cn.getName(), deployedApp);
    
            if (log.isInfoEnabled()) {
                log.info(sm.getString("hostConfig.deployWar.finished",
                    war.getAbsolutePath(), Long.valueOf(System.currentTimeMillis() - startTime)));
            }
        }
  • 相关阅读:
    Proj THUDBFuzz Paper Reading: PMFuzz: Test Case Generation for Persistent Memory Programs
    入围 WF 后训练记
    算法竞赛历程
    2021 多校 杭电 第十场
    2021 多校 杭电 第九场
    2021 多校 牛客 第十场
    2021 多校 牛客 第九场
    2021 多校 杭电 第八场
    2021 多校 杭电 第六场
    2021 多校 杭电 第七场
  • 原文地址:https://www.cnblogs.com/honger/p/10363043.html
Copyright © 2011-2022 走看看