ProductHandler类是真正从product,product content和charging info转换为price plan,入口可以认为是processPricePlans方法。
首 先它调用getUnprocessedCntProductAssoc,这个方法的功能是:1.Get Unprocessed Content and Product associate VO from DB 2.Sort the unprocessed list。这个方法涉及到了ContentProductAssocVO,这里有个机制去判断一个ContentProductAssocVO是否已经被 处理过,逻辑上应该是先比较几个ID:IsmpContentId,IsmpProductId和OpFlag,如果相同,再比较时间戳。但是具体的逻辑 没细看。
获得Content and Product associate VO list后,processPricePlans继续调用processCntProductAssocList, 这个方法的功能是:Fetch all the content and product pair in the content_product_mapping table for this particular content_id。注意这里面提到了CONTENT_PROD_MAP table,这个表很重要。processCntProductAssocList方法调用fetchContent来获得ContentItemVO,注意fetchContent的参数是contentID。
然后processCntProductAssocList调用fetchProcducts, 这个方法有点复杂,它用参数返回好几个map(cntProducts,deletedCntProdMap和omittedCntProdMap,把哪 些product放到哪一个map里是更加opflag来判断的,另外,处理出错的情况都放到omittedCntProdMap里去。)。这个方法会调 用createPriceMethod,这个方法非常重要,它用来生成price method,在manufacture price plan和operation price plan里都能看见(method标签),它的参数有ChargingPolicyVO和ProductVO,前者保存的是电信的收费信息。该方法首先得到charg info的收费方式,在电信文档的附录D中有描述,包括BREW系统原有计费策略和与之相应的ISMP产品计费策略。这些策略一共有九种,但是在createPriceMethod里只处理了5种情况,不知道为什么。
在 fetchProducts的最后有一个逻辑,当OpFlag为delete时,把product放入deletedCntProdMap,如果 OpFlag不是delete,那就是add,但是在之前还要进行判断,如果要add的项也被包含在deletedCntProdMap(两者的 productID相同,也就是一个product既已经被包括在deletedCntProdMap,现在又要将其add),那么就要判断add的项和 delete的项两者的时间戳,如果要add项的时间戳要早于要delete项的时间戳,那就什么也不干(表示这个product最终是要被删除的),反 之,就将给product加入到cntProducts中。
processCntProductAssocList会调用fetchProducts两次,然后processCntProductAssocList调用prepareMfgPricePlan方 法,它的功能是:Prepare the MFG Price plan and generate the meta file. The ISMP price plan to BMC price plan mapping logic are locate inside this method. 说明这个方法很重要,manufacturer price plan文件就是由它构建的。
2009年7月29日星期三
2009年7月28日星期二
CMSEntity之三,谈话整理
昨天下午谈话的整理:
电信这边的产品信息包括:product info,product content和charging info。电信的收费信息是针对product而言的,也就是一个产品它有计费信息,而不是一个内容或者一个电信item有它的计费信息。而BREW这 边,计费信息是针对manufacturer partner number的,每个manufacturer partner number下面包含有多个item,一个manufacturer partner number就相当于一个组,包含多个BREW item,计费信息就是针对这个组的。目前是把manufacturer partner number和电信那边的content视为等价,但其实两者是不同概念。
price plan是BREW这边的概念,它是由product info,product content和charging info这三个文件导出的,四元组:price basis,price method,price value和就包含在price plan中,所以price plan是非常重要的。
Meta.xml和item.zip一起再压缩成一个zip给BMC(这个Meta.xml和item.zip最好能看看里面的内容)。
数 据库的几个表,ISMP_Content,ISMP_Item等等(ISMP Content number什么的,作为key,这个也不知道是什么东西),这个没搞清楚,还有对应product info,product content和charging info每个文件都有一个表,这些表要弄清楚。
对BREW手机和ADS来说,catalog是有多个 的,每个catalog是针对语言来说的,例如英语有英语的一个catalog,汉语有汉语的一个catalog,其它语言有其自己的catalog。每 个catalog可以想象其为一颗树,和pc机上的目录结构是一样的,catalog下有category,也有subcatalog,catalog下 也可以有item,subcatalog下有item等等。
manufacture price plan和operation price plan是高通的遗留东西,但是现在还在使用,两者的区别是operation price plan有change list,但是manufacture price plan没有。
在CMSEntity里的dao包中,有关的表有:
PRODUCT_INFO table,PRODUCT_CHARGE_INFO table,PRODUCT_CHARGE_MODE table,CONTENT_PROD_MAP table,ISMP_ITEM table,ISMP_ITEM_MODELS table,ISMP_ITEM_LANGUAGES table,CHANGE_LIST table,Ismp_Region table等等,目前重点关注PRODUCT_INFO table,PRODUCT_CHARGE_INFO table,PRODUCT_CHARGE_MODE table,CONTENT_PROD_MAP table。
电信这边的产品信息包括:product info,product content和charging info。电信的收费信息是针对product而言的,也就是一个产品它有计费信息,而不是一个内容或者一个电信item有它的计费信息。而BREW这 边,计费信息是针对manufacturer partner number的,每个manufacturer partner number下面包含有多个item,一个manufacturer partner number就相当于一个组,包含多个BREW item,计费信息就是针对这个组的。目前是把manufacturer partner number和电信那边的content视为等价,但其实两者是不同概念。
price plan是BREW这边的概念,它是由product info,product content和charging info这三个文件导出的,四元组:price basis,price method,price value和就包含在price plan中,所以price plan是非常重要的。
Meta.xml和item.zip一起再压缩成一个zip给BMC(这个Meta.xml和item.zip最好能看看里面的内容)。
数 据库的几个表,ISMP_Content,ISMP_Item等等(ISMP Content number什么的,作为key,这个也不知道是什么东西),这个没搞清楚,还有对应product info,product content和charging info每个文件都有一个表,这些表要弄清楚。
对BREW手机和ADS来说,catalog是有多个 的,每个catalog是针对语言来说的,例如英语有英语的一个catalog,汉语有汉语的一个catalog,其它语言有其自己的catalog。每 个catalog可以想象其为一颗树,和pc机上的目录结构是一样的,catalog下有category,也有subcatalog,catalog下 也可以有item,subcatalog下有item等等。
manufacture price plan和operation price plan是高通的遗留东西,但是现在还在使用,两者的区别是operation price plan有change list,但是manufacture price plan没有。
在CMSEntity里的dao包中,有关的表有:
PRODUCT_INFO table,PRODUCT_CHARGE_INFO table,PRODUCT_CHARGE_MODE table,CONTENT_PROD_MAP table,ISMP_ITEM table,ISMP_ITEM_MODELS table,ISMP_ITEM_LANGUAGES table,CHANGE_LIST table,Ismp_Region table等等,目前重点关注PRODUCT_INFO table,PRODUCT_CHARGE_INFO table,PRODUCT_CHARGE_MODE table,CONTENT_PROD_MAP table。
2009年7月27日星期一
CMSEntity之二
com.qualcomm.bss.bsg.cms.job.ContentProcessorJob.execute会调用 com.qualcomm.bss.bsg.cms.process.ContentHandler.invokeProcess,我觉得 ContentHandler应该是真正干活的,它来解析map文件并把内容保存到数据库中。但是 ContentHandler.invokeProcess很简单,它调用了 ContentHandler.commonStorageHandling,在这个方法中对ISMPItemVO,ContentItemVO进行了一 番操作,但是也没看出头绪。
TerminalInfoLoadJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.TerminalInfoLoadJob.execute->com.qualcomm.bss.bsg.cms.job.TerminalInfoLoadJob.loadData
ContentFetcherJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ContentFetcherJob.execute->com.qualcomm.bss.bsg.cms.process.ContentAdaptor.invokeProcess
->com.qualcomm.bss.bsg.cms.CDParserImpl.parseCDFile
ContentProcessorJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ContentProcessorJob.execute->com.qualcomm.bss.bsg.cms.process.ContentHandler.invokeProcess->
com.qualcomm.bss.bsg.cms.process.ContentHandler.commonStorageHandling
ProductInfoFetchJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ProductInfoFetchJob.execute->com.qualcomm.bss.bsg.cms.process.prodAdaptor.processProductFiles
ProductAdaptor里的方法大有可为,很多事情都是在ProductAdaptor里 面做的,看ProductAdaptor类前面的解释,它的功能包括:1,获取product info文件并保存到本地文件夹;2,解析product info文件并保存到数据库;3,获取product content文件并保存到本地文件夹;4,解析product content文件并将数据保存至数据库;5,获取charge info文件并保存到本地文件夹;6,解析charge info文件并将数据保存至数据库;
由此可见,三个map文件都是在ProductAdaptor类里处理的,所以有必要对ProductAdaptor类中的每个方法都细读。
ProductAdaptor.processProductFiles, 这个方法的功能是用ftp获取三个map文件,即product info,product content和charging info。这个方法里用到了类ProductFtpHandler,并对ProductParser类进行了实例化。ProductFtpHandler 是用来获取相应的map文件的,调用它的fetchProductInfoFiles,fetchProductContentFiles和fetchChargingInfoFiles就能获得相应的文件。每当获得相应的文件后,processProductFiles会调用方法来解析获得的文件,这些方法包括processProductInfoFile,processProductContentFiles和processChargingFiles,从名字就很好判断它们的作用。
前面提到processProductFiles实例化了ProductParser,这个类顾名思义,是用来解析product info文件的,但是看这个类的解释,又不仅仅是。ProductParser类只是一个接口,它的实现类是ProductParserImpl, 这个类最前面的注释说:“This class is used to parse product info ,Product content mapping , charging policy info files. Also creates price plan xml files.”,从这段注释可知这个ProductParserImpl不仅仅是解析product info文件,它把三个map文件都解析了,同时生成了price plan文件。前面提到的processProductInfoFile,processProductContentFiles和processChargingFiles方法都使用了ProductParser的实例来解析相应的文件。
ProcessProductInfoFile 先是调用了ProductParserImpl.parseProductFile解析product info文件,它的返回值是ProductInfoVO,然后ProcessProductInfoFile再调用 ProductDAO.addProductInfo将ProductInfoVO的信息写入到数据库中。
processProductContentFiles 处理product content文件,它的处理过程和ProcessProductInfoFile差不多,先是调用 ProductParserImpl.parseProductContentFile解析product content文件,返回值是ProductContentVO,在将ProductContentVO的信息保存到数据库之 前,processProductContentFiles还调用了applyProductContent方法,这个方法是“used to apply products to contents”,不知道是什么意思。但是看代码,这里是生成product和content的关系,这些关系都存放在contentProductAssocVO,这是一个很重要的对象,后面的操作要经常使用这个对象。然后ProcessProductInfoFile再调用ProductDAO.applyProductContent将ProductContentVO的信息写入到数据库中。
processChargingFiles的流程和前两个相似,不赘述。
ProductProcessJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ProductProcessJob.execute->com.qualcomm.bss.bsg.cms.process.ProductHandler.processPricePlans
ProductHandler类是生从电信的那一套(也就是product,content,item和charging info)转换成BREW识别的一套(item和price handle)的关键。具体的实现与数据库非常相关,目前暂时还没研究。
ReleaseProcessJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ReleaseProcessJob.execute->com.qualcomm.bss.bsg.cms.process.ReleaseHandler.invokeProcess
MasterSwitchJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.scheduleMasterSwitch->
FeedBackFileUpLoaderJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.scheduleFeedBackUpLoadProcess->com.qualcomm.bss.bsg.cms.job.FeedBackFileUpLoaderJob
TerminalInfoLoadJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.TerminalInfoLoadJob.execute->com.qualcomm.bss.bsg.cms.job.TerminalInfoLoadJob.loadData
ContentFetcherJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ContentFetcherJob.execute->com.qualcomm.bss.bsg.cms.process.ContentAdaptor.invokeProcess
->com.qualcomm.bss.bsg.cms.CDParserImpl.parseCDFile
ContentProcessorJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ContentProcessorJob.execute->com.qualcomm.bss.bsg.cms.process.ContentHandler.invokeProcess->
com.qualcomm.bss.bsg.cms.process.ContentHandler.commonStorageHandling
ProductInfoFetchJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ProductInfoFetchJob.execute->com.qualcomm.bss.bsg.cms.process.prodAdaptor.processProductFiles
ProductAdaptor里的方法大有可为,很多事情都是在ProductAdaptor里 面做的,看ProductAdaptor类前面的解释,它的功能包括:1,获取product info文件并保存到本地文件夹;2,解析product info文件并保存到数据库;3,获取product content文件并保存到本地文件夹;4,解析product content文件并将数据保存至数据库;5,获取charge info文件并保存到本地文件夹;6,解析charge info文件并将数据保存至数据库;
由此可见,三个map文件都是在ProductAdaptor类里处理的,所以有必要对ProductAdaptor类中的每个方法都细读。
ProductAdaptor.processProductFiles, 这个方法的功能是用ftp获取三个map文件,即product info,product content和charging info。这个方法里用到了类ProductFtpHandler,并对ProductParser类进行了实例化。ProductFtpHandler 是用来获取相应的map文件的,调用它的fetchProductInfoFiles,fetchProductContentFiles和fetchChargingInfoFiles就能获得相应的文件。每当获得相应的文件后,processProductFiles会调用方法来解析获得的文件,这些方法包括processProductInfoFile,processProductContentFiles和processChargingFiles,从名字就很好判断它们的作用。
前面提到processProductFiles实例化了ProductParser,这个类顾名思义,是用来解析product info文件的,但是看这个类的解释,又不仅仅是。ProductParser类只是一个接口,它的实现类是ProductParserImpl, 这个类最前面的注释说:“This class is used to parse product info ,Product content mapping , charging policy info files. Also creates price plan xml files.”,从这段注释可知这个ProductParserImpl不仅仅是解析product info文件,它把三个map文件都解析了,同时生成了price plan文件。前面提到的processProductInfoFile,processProductContentFiles和processChargingFiles方法都使用了ProductParser的实例来解析相应的文件。
ProcessProductInfoFile 先是调用了ProductParserImpl.parseProductFile解析product info文件,它的返回值是ProductInfoVO,然后ProcessProductInfoFile再调用 ProductDAO.addProductInfo将ProductInfoVO的信息写入到数据库中。
processProductContentFiles 处理product content文件,它的处理过程和ProcessProductInfoFile差不多,先是调用 ProductParserImpl.parseProductContentFile解析product content文件,返回值是ProductContentVO,在将ProductContentVO的信息保存到数据库之 前,processProductContentFiles还调用了applyProductContent方法,这个方法是“used to apply products to contents”,不知道是什么意思。但是看代码,这里是生成product和content的关系,这些关系都存放在contentProductAssocVO,这是一个很重要的对象,后面的操作要经常使用这个对象。然后ProcessProductInfoFile再调用ProductDAO.applyProductContent将ProductContentVO的信息写入到数据库中。
processChargingFiles的流程和前两个相似,不赘述。
ProductProcessJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ProductProcessJob.execute->com.qualcomm.bss.bsg.cms.process.ProductHandler.processPricePlans
ProductHandler类是生从电信的那一套(也就是product,content,item和charging info)转换成BREW识别的一套(item和price handle)的关键。具体的实现与数据库非常相关,目前暂时还没研究。
ReleaseProcessJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ReleaseProcessJob.execute->com.qualcomm.bss.bsg.cms.process.ReleaseHandler.invokeProcess
MasterSwitchJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.scheduleMasterSwitch->
FeedBackFileUpLoaderJob:
com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.scheduleFeedBackUpLoadProcess->com.qualcomm.bss.bsg.cms.job.FeedBackFileUpLoaderJob
2009年7月24日星期五
CMSEntity之一,各种Job和VO
contentFetcherJob
ContentProcessorJob
ProductInfoFetchJob
ProductProcessJob
com.chinatelecom.ismp.contentpublish.req包的类ContentSyncNotifyReq
com.chinatelecom.ismp.contentpublish.ContentPublishedReqAdapter
com.chinatelecom.ismp.contentpublish包里的方法ContentPublishedReqAdapterSoapBindingImpl::contentSyncNotify
前 面的关系有点乱,到现在还没理清,按流程应该是ISMP先给BSG发一个contentSyncNotify(一个SOAP call),BSG收到这个notify后去解析它的内容,获得content description文件的存放地址和目录,但是现在还不知道是在哪里处理这个notify的,本以为是在 com.qualcomm.bss.bsg.cms.servicelaye.BSGWebServiceServlet处理这个notify的,但是看 了这个类的doGet方法,感觉这个方法没有处理notify。CMSWebServices和CMSEntity两个工程里面都没找到,这个暂且放下, 以后再找找。
目前看com.chinatelecom.ismp.contentpublish。ContentPublishedReqAdapterSoapBindingImpl::contentSyncNotify是处理notify的(但不知道它是如何被调用的,好像用了一个axis2的东西,google了一下,这是Apache的一个包,但是它是干什么用的没细看)。
方法contentSyncNotify使用了contentSyncNotifyReq, 这个类其实无甚特别,但是其中有一段代码搞得我很迷惑:static{... ...},这段代码和org.apache.axis.description有关,不知道是干嘛的,留到后面再研究。然后 contentSyncNotify调用saveContentSyncInfo将得到的信息保存到数据库中,这个应该是content description文件的存放地址和目录。
com.qualcomm.bss.bsg.cms.parser是一个接口,类CDParserImpl实现了这个接口,里面有个方法:parseCDFile,这个方法就是用来解析content description文件的。
com.qualcomm.bss.bsg.cms.process.ContentAdaptor类中的方法:invokeProcess,调用了parseCDFile。
然 后com.qualcomm.bss.bsg.cms.job.ContentFetcherJob的方法execute中会调用 contentAdaptor.invokeProcess。这个ContentFetcherJob是从StatefulJob继承的类,也就是它是一 个Quterz的类,周期性地执行,
在com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet的init方法中会创建ContentFetcherJob,并对它进行调度。
所 以这几步的流程 是:com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ContentFetcherJob.execute->com.qualcomm.bss.bsg.cms.process.ContentAdaptor.invokeProcess
->com.qualcomm.bss.bsg.cms.CDParserImpl.parseCDFile。
在 ContentAdaptor类里有个方法fetchFile,这个方法其实就是从给定的地址中用FTP去取文件,invokeProcess调用 fetchFile去获取content description文件,content description文件的地址,在前面提到,content description文件的存放地址和目录已经保存在数据库中了。
content description文件解析完后,ContentAdaptor::invokeProcess会调用fetchZipFile去获取zip文件,这 些zip文件就是product_info.map,content_product.map和charge_info.map文件了。文件被取回 后,ContentAdaptor::invokeProcess还调用了:
batchStatusVO.setProcStatCodeID(Constants.BATCH_STATUS_SAVED);
updateBatchStatus(batchStatusVO);
这 两个调用貌似很重要,因为zip文件取回后就要进入下一步的处理,即将这三个map文件解析并将相应的内容填到数据库中,但是处理三个map文件也是一个 job,即ContentProcessJob,这个job也是在 com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init被创建初始化并调度的。也就是说, 它一直周期性地试图去处理三个map文件,但是并不是时时刻刻都有map文件需要处理(因为不是每时每刻都有产品要提交到BMC上去),所以当有新的 map文件被取回后,必须要有一种方法通知ContentProcessJob,现在有新的map文件需要处理了。这个方法应该就是 ContentAdaptor::invokeProcess在取回map文件后,向数据库里写了某些信息,就相当于置了某些标志位,然后 ContentProcessJob在处理过程中首先是查询数据库,获得信息得知是否有新的map文件需要处理。
com.qualcomm.bss.bsg.cms.job.ContentProcessorJob
com.qualcomm.bss.bsg.cms.process.invokeProcess
com.qualcomm.bss.bsg.cms.process.getSuitableBatch
ISMPItemVO
ContentItemVO
ContentProcessorJob
ProductInfoFetchJob
ProductProcessJob
com.chinatelecom.ismp.contentpublish.req包的类ContentSyncNotifyReq
com.chinatelecom.ismp.contentpublish.ContentPublishedReqAdapter
com.chinatelecom.ismp.contentpublish包里的方法ContentPublishedReqAdapterSoapBindingImpl::contentSyncNotify
前 面的关系有点乱,到现在还没理清,按流程应该是ISMP先给BSG发一个contentSyncNotify(一个SOAP call),BSG收到这个notify后去解析它的内容,获得content description文件的存放地址和目录,但是现在还不知道是在哪里处理这个notify的,本以为是在 com.qualcomm.bss.bsg.cms.servicelaye.BSGWebServiceServlet处理这个notify的,但是看 了这个类的doGet方法,感觉这个方法没有处理notify。CMSWebServices和CMSEntity两个工程里面都没找到,这个暂且放下, 以后再找找。
目前看com.chinatelecom.ismp.contentpublish。ContentPublishedReqAdapterSoapBindingImpl::contentSyncNotify是处理notify的(但不知道它是如何被调用的,好像用了一个axis2的东西,google了一下,这是Apache的一个包,但是它是干什么用的没细看)。
方法contentSyncNotify使用了contentSyncNotifyReq, 这个类其实无甚特别,但是其中有一段代码搞得我很迷惑:static{... ...},这段代码和org.apache.axis.description有关,不知道是干嘛的,留到后面再研究。然后 contentSyncNotify调用saveContentSyncInfo将得到的信息保存到数据库中,这个应该是content description文件的存放地址和目录。
com.qualcomm.bss.bsg.cms.parser是一个接口,类CDParserImpl实现了这个接口,里面有个方法:parseCDFile,这个方法就是用来解析content description文件的。
com.qualcomm.bss.bsg.cms.process.ContentAdaptor类中的方法:invokeProcess,调用了parseCDFile。
然 后com.qualcomm.bss.bsg.cms.job.ContentFetcherJob的方法execute中会调用 contentAdaptor.invokeProcess。这个ContentFetcherJob是从StatefulJob继承的类,也就是它是一 个Quterz的类,周期性地执行,
在com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet的init方法中会创建ContentFetcherJob,并对它进行调度。
所 以这几步的流程 是:com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init->com.qualcomm.bss.bsg.cms.job.ContentFetcherJob.execute->com.qualcomm.bss.bsg.cms.process.ContentAdaptor.invokeProcess
->com.qualcomm.bss.bsg.cms.CDParserImpl.parseCDFile。
在 ContentAdaptor类里有个方法fetchFile,这个方法其实就是从给定的地址中用FTP去取文件,invokeProcess调用 fetchFile去获取content description文件,content description文件的地址,在前面提到,content description文件的存放地址和目录已经保存在数据库中了。
content description文件解析完后,ContentAdaptor::invokeProcess会调用fetchZipFile去获取zip文件,这 些zip文件就是product_info.map,content_product.map和charge_info.map文件了。文件被取回 后,ContentAdaptor::invokeProcess还调用了:
batchStatusVO.setProcStatCodeID(Constants.BATCH_STATUS_SAVED);
updateBatchStatus(batchStatusVO);
这 两个调用貌似很重要,因为zip文件取回后就要进入下一步的处理,即将这三个map文件解析并将相应的内容填到数据库中,但是处理三个map文件也是一个 job,即ContentProcessJob,这个job也是在 com.qualcomm.bss.bsg.cms.servicelayer.BSGCMSServlet.init被创建初始化并调度的。也就是说, 它一直周期性地试图去处理三个map文件,但是并不是时时刻刻都有map文件需要处理(因为不是每时每刻都有产品要提交到BMC上去),所以当有新的 map文件被取回后,必须要有一种方法通知ContentProcessJob,现在有新的map文件需要处理了。这个方法应该就是 ContentAdaptor::invokeProcess在取回map文件后,向数据库里写了某些信息,就相当于置了某些标志位,然后 ContentProcessJob在处理过程中首先是查询数据库,获得信息得知是否有新的map文件需要处理。
com.qualcomm.bss.bsg.cms.job.ContentProcessorJob
com.qualcomm.bss.bsg.cms.process.invokeProcess
com.qualcomm.bss.bsg.cms.process.getSuitableBatch
ISMPItemVO
ContentItemVO
2009年7月22日星期三
ISMPEntity之三,2.x和3.x对包月非包月业务的处理流程
包com.qualcomm.bss.bsg.ismpentity.ismpcore中的类ProductPriceObject值得关注,它里面包含了几乎所有重要信息:priceHandle,productID, priceMethod,priceBasis,optionPrice(就是pricevalue),regionId,contentId和optionValue。所以得到ProductPriceObject的实例就可以知道productID等信息。
在 包com.qualcomm.bss.bsg.ismpentity.devices的类Device中有个方 法:getProductPriceObject,可以用它获得ProductPriceObject,getProductPriceObject其实 是去查询数据库来获得ProductPriceObject:
productPriceObject = operationalDataDAO.getPriceHandleMap(String.valueOf(priceHandle), itemId, regionId);
如 果在数据库里查找不到,那么getProductPriceObject会去ISMPConfig里查找postactivition的地 址:String strPostACtivationIPANdURL = ISMPConfig.postActivationURL,根据这个地址,调用方法submitRequest,实际上是去这个地址去访问,返回值是个 字符串,里面包含了ProductPriceObject的所有信息。
3.x手机,下载非包月应用,处理的流程:
1,用户选择好应用后,点击下载
2,手机发出下载鉴权请求给ADS
3,ADS将请求发给BSG
4,经过BSG的router,最终ISMPEntity收到鉴权请求。
5,RequestHandler::doGet->ISMPEntity::invokeService->Locator::locateDeviceHandle->Device::handleRequest
6,Device::handleRequest根据请求的类型来做相应处理,有三种类型的请求:
public enum RequestTypeStatusCodes {
PurAuth,
MsgDownloadAck,
DeleteAck
}
因为是非包月下载请求,所以这里是PurAuth。
7,用Device::getProductPriceObject获得ProductPriceObject对象,该包含了pricehandle,productID等等信息。
8,进入PurAuth处理流程,判读是否包月(这里是非包月),进入非包月处理分支,获得PurchaseAuthorizationHandlerImpl对象。
9, 进入PurchaseAuthorizationHandlerImpl::handleRequest方法,生成 messageID(messageID是联系request和response的桥梁,ISMPEntity会有多个不同的request放在 queue里并发送给ISMP,同时ISMP也会有多个不同的response,request和response必须成对出现,有request必须有 response,某对request和response之间就靠messageID联系,它们必有相同的messageID)并和其它信息 (ismi,itemID,pricehandle等)一起保存到数据库。
10,调用preparePDU构建PDU,然后调用PDURequestHandlerInterface::sendPDU发送PDU。
3.x手机,下载包月应用,处理的流程:
前7步和3.x非包月相同。
8, 进入PurAuth处理流程,判读是包月,进入包月处理分支,获得CreateSubscriptionHandlerImpl对象。
9,进入CreateSubscriptionHandlerImpl::handleRequest方法,包月的创建是用SOAP的,所以调用了方法prepareSOAPRequest去构建并发送SOAP request。
当 ISMP返回成功后,3.x下载包月应用的流程应该和下载非包月的流程一样,再次进入 PurchaseAuthorizationHandlerImpl::handleRequest方法去发送PDU,但是3.x如果再次进入 PurchaseAuthorizationHandlerImpl的处理流程,目前还没有看出来(参考电信文档第8.3.2节"有下载鉴权的包月应用下 载",BSG和ISMP之间是先用SOAP发送了createSubscriptionReq和createSubscriptionResp,然后再和 下载非包月应用一样,发送AuthPrice request和response。我估计因为SOAP还是建立在http协议之上的,所以当ISMP发送createSubscription response给BSG后,ISMPEntitiy还是先进入RequestHandler::doGet,后面的流程就和下载非包月一样了)。
2.x手机,下载非包月应用,处理流程:
前10步和3.x非包月相同。
11,AuthPrice的request PDU发送后,PurchaseAuthorizationHandlerImpl::handleRequest返回到TwoXDeviceImpl::handleRequest。
12, 调用Device::duplicateMsgDownloadAckCheck,这个方法是用来验证MsgDownloadAck是否是已经发送过的 (duplicated),如果是,表明MsgDownloadAck已经被处理过,不用再处理。如果不是,到13步。
13,进入DownloadConfirmationHandlerImpl,调用DownloadConfirmationHandlerImpl::handleRequest方法,发送AuthPricecnfm的PDU。
在 包com.qualcomm.bss.bsg.ismpentity.devices的类Device中有个方 法:getProductPriceObject,可以用它获得ProductPriceObject,getProductPriceObject其实 是去查询数据库来获得ProductPriceObject:
productPriceObject = operationalDataDAO.getPriceHandleMap(String.valueOf(priceHandle), itemId, regionId);
如 果在数据库里查找不到,那么getProductPriceObject会去ISMPConfig里查找postactivition的地 址:String strPostACtivationIPANdURL = ISMPConfig.postActivationURL,根据这个地址,调用方法submitRequest,实际上是去这个地址去访问,返回值是个 字符串,里面包含了ProductPriceObject的所有信息。
3.x手机,下载非包月应用,处理的流程:
1,用户选择好应用后,点击下载
2,手机发出下载鉴权请求给ADS
3,ADS将请求发给BSG
4,经过BSG的router,最终ISMPEntity收到鉴权请求。
5,RequestHandler::doGet->ISMPEntity::invokeService->Locator::locateDeviceHandle->Device::handleRequest
6,Device::handleRequest根据请求的类型来做相应处理,有三种类型的请求:
public enum RequestTypeStatusCodes {
PurAuth,
MsgDownloadAck,
DeleteAck
}
因为是非包月下载请求,所以这里是PurAuth。
7,用Device::getProductPriceObject获得ProductPriceObject对象,该包含了pricehandle,productID等等信息。
8,进入PurAuth处理流程,判读是否包月(这里是非包月),进入非包月处理分支,获得PurchaseAuthorizationHandlerImpl对象。
9, 进入PurchaseAuthorizationHandlerImpl::handleRequest方法,生成 messageID(messageID是联系request和response的桥梁,ISMPEntity会有多个不同的request放在 queue里并发送给ISMP,同时ISMP也会有多个不同的response,request和response必须成对出现,有request必须有 response,某对request和response之间就靠messageID联系,它们必有相同的messageID)并和其它信息 (ismi,itemID,pricehandle等)一起保存到数据库。
10,调用preparePDU构建PDU,然后调用PDURequestHandlerInterface::sendPDU发送PDU。
3.x手机,下载包月应用,处理的流程:
前7步和3.x非包月相同。
8, 进入PurAuth处理流程,判读是包月,进入包月处理分支,获得CreateSubscriptionHandlerImpl对象。
9,进入CreateSubscriptionHandlerImpl::handleRequest方法,包月的创建是用SOAP的,所以调用了方法prepareSOAPRequest去构建并发送SOAP request。
当 ISMP返回成功后,3.x下载包月应用的流程应该和下载非包月的流程一样,再次进入 PurchaseAuthorizationHandlerImpl::handleRequest方法去发送PDU,但是3.x如果再次进入 PurchaseAuthorizationHandlerImpl的处理流程,目前还没有看出来(参考电信文档第8.3.2节"有下载鉴权的包月应用下 载",BSG和ISMP之间是先用SOAP发送了createSubscriptionReq和createSubscriptionResp,然后再和 下载非包月应用一样,发送AuthPrice request和response。我估计因为SOAP还是建立在http协议之上的,所以当ISMP发送createSubscription response给BSG后,ISMPEntitiy还是先进入RequestHandler::doGet,后面的流程就和下载非包月一样了)。
2.x手机,下载非包月应用,处理流程:
前10步和3.x非包月相同。
11,AuthPrice的request PDU发送后,PurchaseAuthorizationHandlerImpl::handleRequest返回到TwoXDeviceImpl::handleRequest。
12, 调用Device::duplicateMsgDownloadAckCheck,这个方法是用来验证MsgDownloadAck是否是已经发送过的 (duplicated),如果是,表明MsgDownloadAck已经被处理过,不用再处理。如果不是,到13步。
13,进入DownloadConfirmationHandlerImpl,调用DownloadConfirmationHandlerImpl::handleRequest方法,发送AuthPricecnfm的PDU。
2009年7月21日星期二
ISMPEntity之二,PDU收发
PDU(Protocol Data Unit 协议数据单元),可以理解为传输协议数据的包,因为电信定义了ISMAP协议,必然有相应格式的包来传输协议的数据,这很好理解,每种协议有其各自的帧格 式。这个可以查看中国电信的文档,附录里有比较详细的介绍。PDU主要分消息头和消息体,消息头包括:PDU的长度,命令ID和序号。命令ID有好多种, 其中有:id_BindReq,id_EnquireLinkReq,id_AuthPriceReq等等,从这些命令ID的名字就一目了然,知道它们是 的作用是什么。
在com.qualcomm.bss.bsg.ismpentity.pdu包中,PDU的基类是BasePDU,是个抽 象类,它的作用也就是给PDU搭个框架,把PDU的公共部分都设置了,剩下和各个命令相关的部分都放到特定命令里去设置。PDU的派生类众多,不过应该都 是大同小异,例如派生类:BindResponsePDU,EnquireLinkRequestPDU等等,从名字就知道它们是构造何种PDU的。
包 com.qualcomm.bss.bsg.ismpentity.ismaphandler有点搞头,里面有些类值得关注,首先是接口 PDURequestHandlerInterface,它包含了一些方法,它们用于发送异步PDU给ISMP,这说明ISMPEntity与ISMP之 间是用异步PDU进行通信的?这个还有待证实。类PDURequestHandlerImpl实现了接口 PDURequestHandlerInterface,具体的实现没细看。
类PDUConnection,对socket进行了封装, 从它的方法:connect和disconnect就很明显,不过这个类的职责并不明晰,它不但包括了对socket的封装,而且它还会发送bind和 unbind的PDU,这一点我决定没设计好,这两个应该是不相关的。
类PDUTransmitter是用来发送PDU的,它用到了 PDUConnection,这是理所当然,它还用到了一个类:PDUWrapper,这个类我没看太明白,不知道有什么用,不过它比较简单,可以暂且放 在一边。PDUTransmitter有个方法generateSeqId产生所谓的sequence ID,我估计这个sequence ID就是电信文档里提到的“用于请求和响应间保持联系的序号”,不过这还是有待证实。在发送的时候用方法 associateSeqToPDUWrapper将sequence ID和PDUWrapper进行绑定,它们是一个键值对,每个sequence ID都对应唯一的PDUWrapper。这个键值对是有用的,在类PDUReceiver中要用到的。
类PDUReceiver和PDUTransmitter做相反的事。
PDU 这一块现在还是有点迷糊,目前看,PDU的操作其实也可以分为两层,上层包括PDURequestsHandlerInterface和 PDURequestsHandlerImpl,这两个类一个是接口一个是实现,它们是给上层用的,其中有个方法是sendPDU,这个方法用来发送 PDU。而其实待发的PDU加入到一个队列中PDUQueue,最终将某个PDU发送出去的是类PDUTransmitter实现的。
调用的大致流程:
RequestHandler::doGet->ISMPEntity::invokeService->Locator::locateDeviceHandle->Device::handleRequest->HandlerInterface::handleRequest->PDURequestHandlerInterface::sendPDU->pduQueue::addToQueue-
>PDUTransmitter->sendPDUBytesToISMP
在com.qualcomm.bss.bsg.ismpentity.pdu包中,PDU的基类是BasePDU,是个抽 象类,它的作用也就是给PDU搭个框架,把PDU的公共部分都设置了,剩下和各个命令相关的部分都放到特定命令里去设置。PDU的派生类众多,不过应该都 是大同小异,例如派生类:BindResponsePDU,EnquireLinkRequestPDU等等,从名字就知道它们是构造何种PDU的。
包 com.qualcomm.bss.bsg.ismpentity.ismaphandler有点搞头,里面有些类值得关注,首先是接口 PDURequestHandlerInterface,它包含了一些方法,它们用于发送异步PDU给ISMP,这说明ISMPEntity与ISMP之 间是用异步PDU进行通信的?这个还有待证实。类PDURequestHandlerImpl实现了接口 PDURequestHandlerInterface,具体的实现没细看。
类PDUConnection,对socket进行了封装, 从它的方法:connect和disconnect就很明显,不过这个类的职责并不明晰,它不但包括了对socket的封装,而且它还会发送bind和 unbind的PDU,这一点我决定没设计好,这两个应该是不相关的。
类PDUTransmitter是用来发送PDU的,它用到了 PDUConnection,这是理所当然,它还用到了一个类:PDUWrapper,这个类我没看太明白,不知道有什么用,不过它比较简单,可以暂且放 在一边。PDUTransmitter有个方法generateSeqId产生所谓的sequence ID,我估计这个sequence ID就是电信文档里提到的“用于请求和响应间保持联系的序号”,不过这还是有待证实。在发送的时候用方法 associateSeqToPDUWrapper将sequence ID和PDUWrapper进行绑定,它们是一个键值对,每个sequence ID都对应唯一的PDUWrapper。这个键值对是有用的,在类PDUReceiver中要用到的。
类PDUReceiver和PDUTransmitter做相反的事。
PDU 这一块现在还是有点迷糊,目前看,PDU的操作其实也可以分为两层,上层包括PDURequestsHandlerInterface和 PDURequestsHandlerImpl,这两个类一个是接口一个是实现,它们是给上层用的,其中有个方法是sendPDU,这个方法用来发送 PDU。而其实待发的PDU加入到一个队列中PDUQueue,最终将某个PDU发送出去的是类PDUTransmitter实现的。
调用的大致流程:
RequestHandler::doGet->ISMPEntity::invokeService->Locator::locateDeviceHandle->Device::handleRequest->HandlerInterface::handleRequest->PDURequestHandlerInterface::sendPDU->pduQueue::addToQueue-
>PDUTransmitter->sendPDUBytesToISMP
2009年7月20日星期一
ISMPEntity之一
ISMPEntity的主要作用:
与ISMP进行绑定或者解绑定(bind,unbind),并维持心跳(heartbeat);管理BDS(BREW Delivery System)与ISMP之间的通信信道,BDS的实时流(用户下载,订购等信息)都是通过ISMPEntity转达给ISMP的。
request 实时流的入口:RequestHandler.java: public void doGet(HttpServletRequest request, HttpServletResponse response),doGet中会调用ISMPEntity.java的方法invokeService,这个方法比较重要,所有手机过来的实时 request,都要经过这个方法,该方法根据它的参数来确认发送request的手持终端的类型,通过这个类型,从类Locator获得相应设备的句 柄,调用相应设备的方法handleRequest来处理终端的request。
其实这里使用的就是多态,设备有多种类型,具体设备都是从一个基类派生的,invokeService根据它的参数确定相应的设备,然后调用设备的方法来处理request,实质上就是使用多态来实现。
前面提到的设备的基类就是DeviceInterface,是位于com.qualcomm.bss.bsg.ismpentity.devices包里的,它是一个接口,里面只有一个方法handleRequest, 抽象类Device实现了这个接口。这个类里面的一些方法有必要关注,但目前还没细看。类TwoXDeviceImpl和 ThreeXDeviceImpl都是从Device派生的,这两个类的名字就很明显了,老谭曾经提到,目前高通有两个平台:较老的2系列和较新的3系 列,这两个类就分别对应的2系列设备和3系列设备。
类HandlerInterface也颇为重要,位于 com.qualcomm.bss.bsg.ismpentity.handler包,它也是个接口,和DeviceInterface本质是相似的,它 对应的是服务的概念,类AppDeletionHandlerImpl,CreateSubscriptionHandlerImpl和 DownloadConfirmationHandlerImpl从HandlerInterface派生,根据三个派生类的名字也可以大概明白它们的作 用:一个处理删除,一个处理包月的创建,一个处理下载确认。注意HandlerInterface接口中也有个很重要的方法叫handleRequest,这个和前面提到的设备的handleRequest不要混淆。在HandlerInterface接口的handleRequest中对收到的request进行了解析,request参考电信文档第八章和第九章,里面有详细request格式介绍。handleRequest按照这个格式进行解析,因为要取出相应的信息来构建PDU。
与ISMP进行绑定或者解绑定(bind,unbind),并维持心跳(heartbeat);管理BDS(BREW Delivery System)与ISMP之间的通信信道,BDS的实时流(用户下载,订购等信息)都是通过ISMPEntity转达给ISMP的。
request 实时流的入口:RequestHandler.java: public void doGet(HttpServletRequest request, HttpServletResponse response),doGet中会调用ISMPEntity.java的方法invokeService,这个方法比较重要,所有手机过来的实时 request,都要经过这个方法,该方法根据它的参数来确认发送request的手持终端的类型,通过这个类型,从类Locator获得相应设备的句 柄,调用相应设备的方法handleRequest来处理终端的request。
其实这里使用的就是多态,设备有多种类型,具体设备都是从一个基类派生的,invokeService根据它的参数确定相应的设备,然后调用设备的方法来处理request,实质上就是使用多态来实现。
前面提到的设备的基类就是DeviceInterface,是位于com.qualcomm.bss.bsg.ismpentity.devices包里的,它是一个接口,里面只有一个方法handleRequest, 抽象类Device实现了这个接口。这个类里面的一些方法有必要关注,但目前还没细看。类TwoXDeviceImpl和 ThreeXDeviceImpl都是从Device派生的,这两个类的名字就很明显了,老谭曾经提到,目前高通有两个平台:较老的2系列和较新的3系 列,这两个类就分别对应的2系列设备和3系列设备。
类HandlerInterface也颇为重要,位于 com.qualcomm.bss.bsg.ismpentity.handler包,它也是个接口,和DeviceInterface本质是相似的,它 对应的是服务的概念,类AppDeletionHandlerImpl,CreateSubscriptionHandlerImpl和 DownloadConfirmationHandlerImpl从HandlerInterface派生,根据三个派生类的名字也可以大概明白它们的作 用:一个处理删除,一个处理包月的创建,一个处理下载确认。注意HandlerInterface接口中也有个很重要的方法叫handleRequest,这个和前面提到的设备的handleRequest不要混淆。在HandlerInterface接口的handleRequest中对收到的request进行了解析,request参考电信文档第八章和第九章,里面有详细request格式介绍。handleRequest按照这个格式进行解析,因为要取出相应的信息来构建PDU。
订阅:
评论 (Atom)