cmsjsploader.java

来自「找了很久才找到到源代码」· Java 代码 · 共 1,284 行 · 第 1/4 页

JAVA
1,284
字号
            buf.append(content.substring(p0, content.length()));
            content = buf.toString();
        }
        return content;
    }

    /**
     * Parses all jsp link macros, and replace them by the right target path.<p>
     * 
     * @param content the content to parse
     * @param controller the request controller
     * 
     * @return the parsed content
     */
    private String parseJspLinkMacros(String content, CmsFlexController controller) {

        CmsJspLinkMacroResolver macroResolver = new CmsJspLinkMacroResolver(controller.getCmsObject(), null, true);
        return macroResolver.resolveMacros(content);
    }

    /**
     * @see org.opencms.loader.I_CmsResourceLoader#service(org.opencms.file.CmsObject, org.opencms.file.CmsResource, javax.servlet.ServletRequest, javax.servlet.ServletResponse)
     */
    public void service(CmsObject cms, CmsResource resource, ServletRequest req, ServletResponse res)
    throws ServletException, IOException, CmsLoaderException {

        CmsFlexController controller = CmsFlexController.getController(req);
        // get JSP target name on "real" file system
        String target = updateJsp(resource, controller, new HashSet(8));
        // important: Indicate that all output must be buffered
        controller.getCurrentResponse().setOnlyBuffering(true);
        // dispatch to external file
        controller.getCurrentRequest().getRequestDispatcherToExternal(cms.getSitePath(resource), target).include(
            req,
            res);
    }

    /**
     * @see org.opencms.loader.I_CmsFlexCacheEnabledLoader#setFlexCache(org.opencms.flex.CmsFlexCache)
     */
    public void setFlexCache(CmsFlexCache cache) {

        m_cache = cache;
        // output setup information
        if (CmsLog.INIT.isInfoEnabled()) {
            CmsLog.INIT.info(Messages.get().getBundle().key(Messages.INIT_ADD_FLEX_CACHE_0));
        }
    }

    /**
     * Delivers the plain uninterpreted resource with escaped XML.<p>
     * 
     * This is intended for viewing historical versions.<p>
     * 
     * @param cms the initialized CmsObject which provides user permissions
     * @param file the requested OpenCms VFS resource
     * @param req the servlet request
     * @param res the servlet response
     * 
     * @throws IOException might be thrown by the servlet environment
     * @throws CmsException in case of errors acessing OpenCms functions
     */
    private void showSource(CmsObject cms, CmsResource file, HttpServletRequest req, HttpServletResponse res)
    throws CmsException, IOException {

        CmsResource historyResource = (CmsResource)CmsHistoryResourceHandler.getHistoryResource(req);
        if (historyResource == null) {
            historyResource = file;
        }
        CmsFile historyFile = cms.readFile(historyResource);
        String content = new String(historyFile.getContents());
        // change the content-type header so that browsers show plain text
        res.setContentLength(content.length());
        res.setContentType("text/plain");

        Writer out = res.getWriter();
        out.write(content);
    }

    /**
     * Updates a JSP page in the "real" file system in case the VFS resource has changed.<p>
     * 
     * Also processes the <code>&lt;%@ cms %&gt;</code> tags before the JSP is written to the real FS.
     * Also recursivly updates all files that are referenced by a <code>&lt;%@ cms %&gt;</code> tag 
     * on this page to make sure the file actually exists in the real FS. 
     * All <code>&lt;%@ include %&gt;</code> tags are parsed and the name in the tag is translated
     * from the OpenCms VFS path to the path in the real FS. 
     * The same is done for filenames in <code>&lt;%@ page errorPage=... %&gt;</code> tags.
     * 
     * @param resource the reqested JSP file resource in the VFS
     * @param controller the controller for the JSP integration
     * @param updatedFiles a Set containing all JSP pages that have been already updated
     * @return the file name of the updated JSP in the "real" FS
     * 
     * @throws ServletException might be thrown in the process of including the JSP 
     * @throws IOException might be thrown in the process of including the JSP 
     * @throws CmsLoaderException if the resource type can not be read
     */
    private String updateJsp(CmsResource resource, CmsFlexController controller, Set updatedFiles)
    throws IOException, ServletException, CmsLoaderException {

        String jspVfsName = resource.getRootPath();
        String extension;
        boolean isHardInclude;
        int loaderId = OpenCms.getResourceManager().getResourceType(resource.getTypeId()).getLoaderId();
        if ((loaderId == CmsJspLoader.RESOURCE_LOADER_ID) && (!jspVfsName.endsWith(JSP_EXTENSION))) {
            // this is a true JSP resource that does not end with ".jsp"
            extension = JSP_EXTENSION;
            isHardInclude = false;
        } else {
            // not a JSP resource or already ends with ".jsp"
            extension = "";
            // if this is a JSP we don't treat it as hard include
            isHardInclude = (loaderId != CmsJspLoader.RESOURCE_LOADER_ID);
        }

        String jspTargetName = CmsFileUtil.getRepositoryName(
            m_jspWebAppRepository,
            jspVfsName + extension,
            controller.getCurrentRequest().isOnline());

        // check if page was already updated
        if (updatedFiles.contains(jspTargetName)) {
            // no need to write the already included file to the real FS more then once
            return jspTargetName;
        }

        String jspPath = CmsFileUtil.getRepositoryName(
            m_jspRepository,
            jspVfsName + extension,
            controller.getCurrentRequest().isOnline());

        File d = new File(jspPath).getParentFile();
        if ((d == null) || (d.exists() && !(d.isDirectory() && d.canRead()))) {
            CmsMessageContainer message = Messages.get().container(Messages.LOG_ACCESS_DENIED_1, jspPath);
            LOG.error(message.key());
            // can not continue
            throw new ServletException(message.key());
        }

        if (!d.exists()) {
            // create directory structure
            d.mkdirs();
        }

        // check if the JSP must be updated
        boolean mustUpdate = false;
        File f = new File(jspPath);
        if (!f.exists()) {
            // file does not exist in real FS
            mustUpdate = true;
            // make sure the parent folder exists
            File folder = f.getParentFile();
            if (!folder.exists()) {
                boolean success = folder.mkdirs();
                if (!success) {
                    LOG.error(org.opencms.db.Messages.get().getBundle().key(
                        org.opencms.db.Messages.LOG_CREATE_FOLDER_FAILED_1,
                        folder.getAbsolutePath()));
                }
            }
        } else if (f.lastModified() <= resource.getDateLastModified()) {
            // file in real FS is older then file in VFS
            mustUpdate = true;
        } else if (controller.getCurrentRequest().isDoRecompile()) {
            // recompile is forced with parameter
            mustUpdate = true;
        } else {
            // update strong link dependencies
            mustUpdate = updateStrongLinks(resource, controller, updatedFiles);
        }

        if (mustUpdate) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_WRITING_JSP_1, jspTargetName));
            }
            updatedFiles.add(jspTargetName);
            byte[] contents;
            String encoding;
            try {
                CmsObject cms = controller.getCmsObject();
                contents = cms.readFile(resource).getContents();
                // check the "content-encoding" property for the JSP, use system default if not found on path
                encoding = cms.readPropertyObject(resource, CmsPropertyDefinition.PROPERTY_CONTENT_ENCODING, true).getValue();
                if (encoding == null) {
                    encoding = OpenCms.getSystemInfo().getDefaultEncoding();
                } else {
                    encoding = CmsEncoder.lookupEncoding(encoding.trim(), encoding);
                }
            } catch (CmsException e) {
                controller.setThrowable(e, jspVfsName);
                throw new ServletException(
                    Messages.get().getBundle().key(Messages.ERR_LOADER_JSP_ACCESS_1, jspVfsName),
                    e);
            }

            try {
                // parse the JSP and modify OpenCms critical directives
                contents = parseJsp(contents, encoding, controller, updatedFiles, isHardInclude);
                if (LOG.isInfoEnabled()) {
                    // check for existing file and display some debug info
                    LOG.info(Messages.get().getBundle().key(
                        Messages.LOG_JSP_PERMCHECK_4,
                        new Object[] {
                            f.getAbsolutePath(),
                            Boolean.valueOf(f.exists()),
                            Boolean.valueOf(f.isFile()),
                            Boolean.valueOf(f.canWrite())}));
                }
                // write the parsed JSP content to the real FS
                synchronized (this) {
                    // this must be done only one file at a time
                    FileOutputStream fs = new FileOutputStream(f);
                    fs.write(contents);
                    fs.close();
                }
                if (LOG.isInfoEnabled()) {
                    LOG.info(Messages.get().getBundle().key(Messages.LOG_UPDATED_JSP_2, jspTargetName, jspVfsName));
                }
            } catch (FileNotFoundException e) {
                throw new ServletException(
                    Messages.get().getBundle().key(Messages.ERR_LOADER_JSP_WRITE_1, f.getName()),
                    e);
            }
        }

        // update "last modified" and "expires" date on controller
        controller.updateDates(f.lastModified(), CmsResource.DATE_EXPIRED_DEFAULT);

        return jspTargetName;
    }

    /**
     * Updates a JSP page in the "real" file system in case the VFS resource has changed based on the resource name.<p>
     * 
     * Gernates a resource based on the provided name and calls {@link #updateJsp(CmsResource, CmsFlexController, Set)}.<p>
     * 
     * @param vfsName the name of the JSP file resource in the VFS
     * @param controller the controller for the JSP integration
     * @param updatedFiles a Set containing all JSP pages that have been already updated
     * @return the file name of the updated JSP in the "real" FS
     */
    private String updateJsp(String vfsName, CmsFlexController controller, Set updatedFiles) {

        String jspVfsName = CmsLinkManager.getAbsoluteUri(vfsName, controller.getCurrentRequest().getElementRootPath());
        if (LOG.isDebugEnabled()) {
            LOG.debug(Messages.get().getBundle().key(Messages.LOG_UPDATE_JSP_1, jspVfsName));
        }
        String jspRfsName;
        try {
            // create an OpenCms user context that operates in the root site
            CmsObject cms = OpenCms.initCmsObject(controller.getCmsObject());
            cms.getRequestContext().setSiteRoot("");
            CmsResource includeResource = cms.readResource(jspVfsName);
            // make sure the jsp referenced file is generated
            jspRfsName = updateJsp(includeResource, controller, updatedFiles);
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_NAME_REAL_FS_1, jspRfsName));
            }
        } catch (Exception e) {
            jspRfsName = null;
            if (LOG.isDebugEnabled()) {
                LOG.debug(Messages.get().getBundle().key(Messages.LOG_ERR_UPDATE_1, jspVfsName), e);
            }
        }
        return jspRfsName;
    }

    /**
     * Updates all jsp files that include the given jsp file using the 'link.strong' macro.<p>
     * 
     * @param resource the current updated jsp file
     * @param controller the controller for the jsp integration
     * @param updatedFiles the already updated files
     * 
     * @return <code>true</code> if the given JSP file should be updated due to dirty included files
     * 
     * @throws ServletException might be thrown in the process of including the JSP 
     * @throws IOException might be thrown in the process of including the JSP 
     * @throws CmsLoaderException if the resource type can not be read
     */
    private boolean updateStrongLinks(CmsResource resource, CmsFlexController controller, Set updatedFiles)
    throws CmsLoaderException, IOException, ServletException {

        int numberOfUpdates = updatedFiles.size();
        CmsObject cms = controller.getCmsObject();
        CmsRelationFilter filter = CmsRelationFilter.TARGETS.filterType(CmsRelationType.JSP_STRONG);
        Iterator it;
        try {
            it = cms.getRelationsForResource(cms.getSitePath(resource), filter).iterator();
        } catch (CmsException e) {
            // should never happen
            if (LOG.isErrorEnabled()) {
                LOG.error(e.getLocalizedMessage(), e);
            }
            return false;
        }
        while (it.hasNext()) {
            CmsRelation relation = (CmsRelation)it.next();
            CmsResource target = null;
            try {
                target = relation.getTarget(cms, CmsResourceFilter.DEFAULT);
            } catch (CmsException e) {
                // should never happen
                if (LOG.isErrorEnabled()) {
                    LOG.error(e.getLocalizedMessage(), e);
                }
                continue;
            }
            // check if page was already updated
            if (updatedFiles.contains(target.getRootPath())) {
                // no need to write the included file to the real FS more than once
                continue;
            }
            // update the target
            updateJsp(target, controller, updatedFiles);
        }
        // the current jsp file should be updated only if one of the included jsp has been updated
        return numberOfUpdates < updatedFiles.size();
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?