📄 cmsjsploader.java
字号:
// multiple page encoding settings if a templete is composed from several hard included elements
// this is an issue in Tomcat 4.x but not 5.x
StringBuffer buf2 = new StringBuffer(buf.length() + 32);
buf2.append("<%@ page pageEncoding=\"");
buf2.append(encoding);
buf2.append("\" %>");
buf2.append(buf);
content = buf2.toString();
}
return content;
}
/**
* Parses the JSP content for includes and replaces all OpenCms VFS
* path information with information for the real FS.<p>
*
* @param content the JSP content to parse
* @param controller the current JSP controller
* @param includes a set of already parsed includes
* @return the parsed JSP content
*/
private String parseJspIncludes(String content, CmsFlexController controller, Set includes) {
// check if a JSP directive occurs in the file
int i1 = content.indexOf(DIRECTIVE_START);
if (i1 < 0) {
// no directive occurs
return content;
}
StringBuffer buf = new StringBuffer(content.length());
int p0 = 0, i2 = 0, slen = DIRECTIVE_START.length();
while (i1 >= 0) {
// parse the file and replace JSP filename references
i2 = content.indexOf(DIRECTIVE_END, i1 + slen);
if (i2 < 0) {
// wrong syntax (missing end directive) - let the JSP compiler produce the error message
return content;
} else if (i2 > i1) {
String directive = content.substring(i1 + slen, i2);
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(
Messages.LOG_DIRECTIVE_DETECTED_3,
DIRECTIVE_START,
directive,
DIRECTIVE_END));
}
int t1 = 0, t2 = 0, t3 = 0, t4 = 0, t5 = 0;
while (directive.charAt(t1) == ' ') {
t1++;
}
String argument = null;
if (directive.startsWith("include", t1)) {
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_X_DIRECTIVE_DETECTED_1, "include"));
}
t2 = directive.indexOf("file", t1 + 7);
t5 = 6;
} else if (directive.startsWith("page", t1)) {
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_X_DIRECTIVE_DETECTED_1, "page"));
}
t2 = directive.indexOf("errorPage", t1 + 4);
t5 = 11;
}
if (t2 > 0) {
String sub = directive.substring(t2 + t5);
char c1 = sub.charAt(t3);
while ((c1 == ' ') || (c1 == '=') || (c1 == '"')) {
c1 = sub.charAt(++t3);
}
t4 = t3;
while (c1 != '"') {
c1 = sub.charAt(++t4);
}
if (t4 > t3) {
argument = sub.substring(t3, t4);
}
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_DIRECTIVE_ARG_1, argument));
}
}
if (argument != null) {
// a file was found, changes have to be made
String pre = directive.substring(0, t2 + t3 + t5);
String suf = directive.substring(t2 + t3 + t5 + argument.length());
// now try to update the referenced file
String jspname = updateJsp(argument, controller, includes);
if (jspname != null) {
// only change something in case no error had occured
directive = pre + jspname + suf;
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(
Messages.LOG_DIRECTIVE_CHANGED_3,
DIRECTIVE_START,
directive,
DIRECTIVE_END));
}
}
}
buf.append(content.substring(p0, i1 + slen));
buf.append(directive);
p0 = i2;
i1 = content.indexOf(DIRECTIVE_START, p0);
}
}
if (i2 > 0) {
// the content of the JSP was changed
buf.append(content.substring(p0, content.length()));
content = buf.toString();
}
return content;
}
/**
* Updates a JSP page in the "real" file system in case the VFS resource has changed.<p>
*
* Also processes the <code><%@ cms %></code> tags before the JSP is written to the real FS.
* Also recursivly updates all files that are referenced by a <code><%@ cms %></code> tag
* on this page to make sure the file actually exists in the real FS.
* All <code><%@ include %></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><%@ page errorPage=... %></code> tags.
*
* @param resource the reqested JSP file resource in the VFS
* @param controller the controller for the JSP integration
* @param updates 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 updates)
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 (updates.contains(jspTargetName)) {
// no need to write the already included file to the real FS more then once
return jspTargetName;
}
updates.add(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 muse be updated
boolean mustUpdate = false;
File f = new File(jspPath);
if (!f.exists()) {
// file does not exist in real FS
mustUpdate = true;
} 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;
}
if (mustUpdate) {
if (LOG.isDebugEnabled()) {
LOG.debug(Messages.get().getBundle().key(Messages.LOG_WRITING_JSP_1, jspTargetName));
}
byte[] contents;
String encoding;
try {
CmsObject cms = controller.getCmsObject();
contents = CmsFile.upgrade(resource, cms).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, updates, isHardInclude);
// 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();
}
contents = null;
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 includes a Set containing all JSP pages that have been already included (i.e. updated)
* @return the file name of the updated JSP in the "real" FS
*/
private String updateJsp(String vfsName, CmsFlexController controller, Set includes) {
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 = null;
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, includes);
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;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -