初次接触tomcat6.0和Heritrix遇到了配置不成功的问题,在读入Heritrix的properties的文件时发生了找不到配置文件的错误,其错误内容如下:
java.io.IOException: Failed to load properties file from filesystem or from classpath.
at org.archive.crawler.Heritrix.getPropertiesInputStream(Heritrix.java:936)
at org.archive.crawler.Heritrix.loadProperties(Heritrix.java:866)
at org.archive.crawler.Heritrix.getJobsdir(Heritrix.java:772)
at org.archive.crawler.Heritrix.<init>(Heritrix.java:405)
at org.archive.crawler.Heritrix.<init>(Heritrix.java:393)
at org.archive.crawler.WebappLifecycle.contextInitialized(WebappLifecycle.java:41)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3843)
at org.apache.catalina.core.StandardContext.start(StandardContext.java:4342)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:525)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:926)
at org.apache.catalina.startup.HostConfig.deployDirectories(HostConfig.java:889)
at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:492)
at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1149)
at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
at org.apache.catalina.core.StandardHost.start(StandardHost.java:719)
at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:443)
at org.apache.catalina.core.StandardService.start(StandardService.java:516)
at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
at org.apache.catalina.startup.Catalina.start(Catalina.java:578)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:623)
at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:288)
at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
在诸多高手的帮助下,通过debug发现以下问题(本人新手,程序运行过程有部分属于个人猜测,时间有限未能仔细检索资料进行核对,望高手指点,板砖轻砸,叙述不严格,只求看懂,经不起推敲)首先用tomcat6.0的模式debug Heritrix.java,在System.class的setProperty()方法中设置断点打对勾的为这个调试过程中需要的断点。如图1所示
图1:
在启动后,程序进程如图2所示:
图2
程序会停止在getProperty(String key)方法上,并加载一些Property。就是说tomcat6.0启动时在比较靠前的步骤里加载系统的Property(个人猜测)。在加载完这些Property后,程序执行ClassLoader.loadClassInternal(String name)方法,其进程如图3所示
图3
继续运行进程如图4所示
图4
继续运行,个人认为无关紧要的就不说了(希望不会漏掉什么),一直到图5
图5
图5开始加载tomcat的Bootstrap。tomcat貌似从这段程序开始真正的运行(个人猜测,书上好像是这样写的)。中有CatalinaProperties.loadProperties()方法。这个方法的功能是加载各种配置,但是没有加载Heritrix的Properties,要不然后面就不会出错了它调用System.setProperty(String,String)方法,这时开始加载各种Properties(个人猜测)。
继续运行,一直加载,在此过程中好像要从各个xml文档中读取信息,这里略去,因为项目里面的xml文档没有关于自己的Properties的信息。这些xml文档就是定义些监听器,过滤器,配置JSP的名字之类的。一直运行到图6
图6
其中第一个方法:contextInitialized开始初始化Heritrix对象。其中的一个方法是Heritrix.isCommandLine()的解释是Returns true if Heritrix was launched from the command line. (When launched from command line, we do stuff like put up a web server to manage our web interface and we register ourselves with the first available jmx agent),是不是可以认为在命令行里初始化Heritrix对象呢,就是在虚拟DOS窗口下?在这里假设不是在命令行里(个人假设)这个假设是从字面意思上理解的:(isCommandLine:在命令行上)显然这样的运行方式不是命令行的。
继续debug,进入(debug中的step into按钮)Heritrix的构造函数。进入到这个构造函数:public Heritrix(final String name, final boolean jmxregister)
throws IOException {
this(name, jmxregister, new CrawlJobHandler(getJobsdir()));
}
接着进入getJobsdir()函数,其主要功能是The directory into which we put jobs. If the system property 'heritrix.jobsdir' is set, we will use its value in place of the default 'jobs' directory in the current working directory.个人理解是定义爬虫的工作位置,首先从system property查找是不是有预定义,这里是查不到的,因为前面一直没有加载heritrix的property。
继续运行这个函数,函数体中的loadProperties()方法是找不到对应的property的,在第一次运行loadProperties()方法时会判断Heritrix.propertiesLoaded的值,这个值的意思是是不是已经加载了Heritrix的properties,默认是false,这就说明Heritrix到此为止一直默认自己的properties是没有加载的,也就是说默认以前tomcat启动过程中不加载Heritrix的properties,如果默认tomcat是加载Heritrix的properties的话,那么Heritrix.propertiesLoaded应该是true才对,也就是说以前没有加载Heritrix的properties是对的,至少不是错的……。(个人猜测)
下面就要执行properties.load(getPropertiesInputStream());首先执行getPropertiesInputStream()方法,在这个方法中应该找到Heritrix存放properties的文件。第一次执行这个方法时肯定不会从系统已经得到的properties中找到路径。而且在注释中有这么一句话:// Look to see if properties have been passed on the cmd-line.紧挨着这句话的下一条语句是String alternateProperties = System.getProperty(PROPERTIES_KEY);这样就可以看出只有在命令行进行配置后,才能从System中得到已经加载的值,否则无法得到,这也间接证实了上面的猜测(如果cmd-line就是指那个DOS黑窗口的话)。
程序只能通过getConfdir()方法得到配置文件夹的路径。
下面运行getConfdir()方法,同样在getConfdir()方法中也有上面提到的关于cmd-line的注释。不管他,继续运行,反正从已有的properties得不到想要的参数。紧接着就是运行getSubDir("conf", fail);方法。其中conf是默认的properties文件所在的文件夹名,fail的值是false。在getSubDir(String subdirName, boolean fail)方法中会运行到File dir = new File(getHeritrixHome(), path);这一步。关键就在于getHeritrixHome()这个方法了。
运行getHeritrixHome()方法,在这个方法中一样从已有的properties得不到信息,于是他执行heritrixHome = new File(new File("").getAbsolutePath());语句,得到正在运行的目录,在我的机器上是D:/tomcat/apache-tomcat-6.0.18/bin,然后返回到getSubDir(String subdirName, boolean fail)方法,这时,此方法中的File类型的dir对象表示的路径是:D:/tomcat/apache-tomcat-6.0.18/bin/conf。到此为止就应该知道问题所在了,如果Heritrix的配置文件没有放到上面指定的路径的话就会报错。比如说我把D:/tomcat/apache-tomcat-6.0.18/bin/下的conf文件夹改名为conf1.如图7
图7
继续运行程序就会抛出上述错误,
这样就找到了症结所在,就知道怎么改了。有两种改正方法:一是把Heritrix的conf文件夹放在tomcat的bin里面,这样就能正常读取,另外一种就是改写源代码,把那个产生路径的函数的结果改成你想产生路径,然后把配置文件放在那个路径下就可以了。
做上述的分析用到了很多假设,其中最为重要的一点就是在产生Heritrix对象之前,假设tomcat没有得到Heritrix的配置文件的行为是不错的,也就是说不是程序或者服务器的错误阻止其得到Heritrix的配置文件,而是程序正常运行的结果。这个假设贯穿始终,但我不确定这个假设是对是错,还请高手指点。(个人意见)
本人初学者,希望被骂的不要太厉害就行了呵呵。
后续:改过来之后发现Heritrix可以运行,但是tomcat的那个tom猫主页无法打开,不知道是不是配置文件的错误,继续研究中。