2021SC@SDUSC
这是我的第十三篇博客,分析的代码还是sitemap-impl文件夹下的内容,这一次我选择了三个文件夹,第一个是classloader文件夹,顾名思义这可能与类的加载有关;另一个文件夹——matching进行分析,这个文件夹里有3个抽象的类;最后一个是objectmodel文件夹。由于考虑到分析代码要选择重要的分析,所以我可能会挑选部分代码进行分析。
文章目录
classloader
AbstractClassLoaderFactory.java
这个java类文件实现了ClassLoaderFactory接口的抽象实现。它同时接受类目录和jar目录配置。还可以指定通配符模式来包含或排除要在类加载器中加载的某些类。在这种情况下,类直接从父类加载器加载。默认是包含所有类。
主要有四个方法:
1.createClassLoader()
——重载,创建类加载器
public ClassLoader createClassLoader(ClassLoader parent,
ClassLoaderConfiguration config,
ServletContext servletContext)
throws Exception {
final List urlList = new ArrayList();
Iterator i;
i = config.getClassDirectories().iterator();
while ( i.hasNext() ) {
final String directory = (String)i.next();
URL url = this.getUrl(servletContext, directory);
if ( url == null ) {
throw new Exception("Directory not found for classpath: " + directory);
}
if ( !url.toExternalForm().endsWith("/") ) {
url = new URL(url.toExternalForm() + "/");
}
urlList.add(url);
}
i = config.getLibDirectories().iterator();
while ( i.hasNext() ) {
final String directory = (String)i.next();
final File libDir = this.getFile(directory);
if ( libDir != null ) {
if ( !libDir.exists() ) {
throw new Exception("Directory for lib class path does not exists: " + libDir);
}
if ( !libDir.isDirectory() ) {
throw new Exception("Configuration for lib class path is not a directory: " + libDir);
}
File[] libraries = libDir.listFiles(new JarFileFilter());
Arrays.sort(libraries);
for (int m = 0; m < libraries.length; m++) {
final URL lib = libraries[m].toURL();
urlList.add(lib);
}
} else {
if ( directory.indexOf(":/") > 0 ) {
throw new Exception("Can't handle absolute url as lib class path: " + directory);
}
final String contextPath = this.getContextPath(directory);
final Set resources = servletContext.getResourcePaths(contextPath + '/');
if ( resources != null ) {
final List temporaryList = new ArrayList();
final Iterator iter = resources.iterator();
while ( iter.hasNext() ) {
final String path = (String)iter.next();
if (path.endsWith(".jar") || path.endsWith(".zip")) {
temporaryList.add(servletContext.getResource(path));
}
}
Collections.sort(temporaryList, new UrlComparator());
urlList.addAll(temporaryList);
}
}
}
URL[] urls = (URL[])urlList.toArray(new URL[urlList.size()]);
return this.createClassLoader(urls, config.getIncludes(), config.getExcludes(), parent);
}
//重载
protected abstract ClassLoader createClassLoader(URL[] urls, List includePatterns, List excludePatterns, ClassLoader parent);
2.getContextPath()
——得到上下文的路径
protected String getContextPath(String path) {
if ( path.startsWith("context://") ) {
return path.substring(9);
}
return "/" + path;
}
3.getFile()
——通过路径得到文件
protected File getFile(String path)
throws MalformedURLException {
if ( path.startsWith("file:") ) {
return new File(path.substring(5));
}
if ( path.startsWith("/") || (path.length() > 2 && path.charAt(1) == ':' )) {
return new File(path);
}
return null;
}
4.grtURL()
——方法内调用了getFile()
方法,用于获得URL
protected URL getUrl(ServletContext servletContext, String path)
throws MalformedURLException {
final File file = this.getFile(path);
if ( file != null ) {
return file.toURL();
}
if ( path.indexOf(":/") > 0 ) {
return new URL(path);
}
return servletContext.getResource(this.getContextPath(path));
}
DefaultClassLoader.java
这个类加载器反转类的搜索顺序。它在检查它的父类之前检查这个类装入器。此外,还可以配置包含和排除。
重要方法:
1.addDirectory()
——用于添加类文件目录:
public final void addDirectory(File file) throws IOException {
this.addURL(file.getCanonicalFile().toURL());
}
2.addURL()
用于添加一个新的URL:
public void addURL(URL url) {
super.addURL(url);
}
3.getResource()
——用于从这个类加载器获取资源:
从这个ClassLoader
中获取资源。如果这个资源不存在,我们就检查父资源。请注意,这与ClassLoader
规范完全相反,我们使用它来处理来自第三方供应商的不一致的类装入器。
public final URL getResource(final String name) {
URL resource = findResource(name);
ClassLoader parent = this.getParent();
if (resource == null && parent != null) {
resource = parent.getResource(name);
}
return resource;
}
4.loadClass()
——用于从这个类加载器加载类:
从这个ClassLoader
中加载类。如果这个类不存在,我们就检查父类。请注意,这与ClassLoader
规范完全相反,我们使用它来处理来自第三方供应商的不一致的类装入器。
public final Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
//首先检查它是否已经加载
Class clazz = findLoadedClass(name);
if (clazz == null) {
final ClassLoader parent = getParent();
if (tryClassHere(name)) {
try {
clazz = this.getClass(name);
} catch (ClassNotFoundException cnfe) {
if (parent == null) {
//传播异常
throw cnfe;
}
}
}
if (clazz == null) {
if (parent == null) {
throw new ClassNotFoundException(name);
} else {
//将抛出一个ClassNotFoundException异常如果没有在父类中发现
clazz = parent.loadClass(name);
}
}
}
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
NotifyingResourceStore.java
这是classloader文件夹下的reloading文件夹里的一个java类文件。
将配置的所有存储打包到站点地图类加载器中,以便将通知事件分派给树处理程序,并强制在cocoon TODO Extend TransactionalResourceStore中重新加载组件(如果存储不是私有的)。
matching
类的名称 | 类的说明 |
---|---|
AbstractPreparableMatcher | 一个匹配器,可以在站点地图设置期间准备模式,以便在请求时更快地匹配。 |
AbstractRegexpMatcher | 使用正则表达式模式的所有匹配器的基类。 |
AbstractWildcardMatcher | 通配符匹配器的基类 |
AbstractPreparableMatcher.java
这也是一个常规的匹配器,这意味着站点地图可以决定是准备模式还是匹配请求时评估的模式。
里面写了一个唯一的方法——match()
通过准备模式并匹配准备好的模式来匹配模式。
public Map match (String pattern, Map objectModel, Parameters parameters)
throws PatternException {
return preparedMatch(preparePattern(pattern), objectModel, parameters);
}
AbstractRegexpMatcher.java
在这个类文件里,主要有3个方法。
1.preparePattern()
——将准备好的模式与getMatchString(Map, Parameters)
返回的值进行匹配。
public Object preparePattern(String pattern) throws PatternException {
//如果pattern为空,返回null以允许在preparedMatch()中抛出定位异常
if (pattern == null) {
return null;
}
if (pattern.length() == 0) {
pattern = "^$";
if (getLogger().isWarnEnabled()) {
getLogger().warn("The empty pattern string was rewritten to '^$'" + " to match for empty strings. If you intended"+ " to match all strings, please change your"+ " pattern to '.*'");
}
}
try {
RECompiler compiler = new RECompiler();
REProgram program = compiler.compile(pattern);
return program;
} catch (RESyntaxException rse) {
getLogger().debug("Failed to compile the pattern '" + pattern + "'", rse);
throw new PatternException(rse.getMessage(), rse);
}
}
2.preparedMatch()
——根据getMatchString(Map, Parameters)
返回的值匹配准备好的模式。
public Map preparedMatch(Object preparedPattern, Map objectModel, Parameters parameters) throws PatternException {
if(preparedPattern == null) {
throw new PatternException("A pattern is needed at " + SitemapParameters.getLocation(parameters));
}
RE re = new RE((REProgram)preparedPattern);
String match = getMatchString(objectModel, parameters);
if (match == null)
return null;
if(re.match(match)) {
int parenCount = re.getParenCount();
Map map = new HashMap();
for (int paren = 0; paren <= parenCount; paren++) {
map.put(Integer.toString(paren), re.getParen(paren));
}
return map;
}
return null;
}
3.getMatchString()
——根据正则表达式获得要测试的字符串。由具体的子类定义。
protected abstract String getMatchString(Map objectModel, Parameters parameters);
AbstractWildcardMatcher.java
主要有两个比较重要的方法:
1.match()
——将准备好的模式与getMatchString(Map, Parameters)
的结果进行匹配。
public Map match(String pattern, Map objectModel, Parameters parameters) throws PatternException {
if (pattern == null) {
throw new PatternException("A pattern is needed at " + SitemapParameters.getLocation(parameters));
}
final String match = getMatchString(objectModel, parameters);
if (match == null) {
return null;
}
return WildcardMatcherHelper.match(pattern, match);
}
2.getMatchString()
——根据通配符表达式获取要测试的字符串。
protected abstract String getMatchString(Map objectModel, Parameters parameters);
objectmodel
objectmodel文件夹内一共有两个文件夹,一个是helpe,另一个是impl。这两个文件内各有一个java文件,分别为ParametersMap.java和CocoonEntryObjectModelProvider.java
类的名称 | 类的说明 |
---|---|
ParametersMap.java | 通过Map接口公开参数的Parameters类的包装器类。如果想在ObjectModel中放置参数,请使用此包装器。 |
CocoonEntryObjectModelProvider.java | 这是提供Concoon的入口文件。 |