1: """CDLI extensions of the filearchive"""
2: from Products.versionedFile.extVersionedFile import *
3: from Products.ZCatalog.CatalogPathAwareness import CatalogAware
4: import os.path
5: import os
6: import urlparse
7: import urllib
8: import cgi
9: from OFS.OrderedFolder import OrderedFolder
10: from OFS.SimpleItem import SimpleItem
11: import time
12: from OFS.Folder import manage_addFolder
13: import re
14: from AccessControl import ClassSecurityInfo
15: from Acquisition import Implicit
16: from Globals import Persistent
17: from threading import Thread
18: from ZPublisher.HTTPRequest import HTTPRequest
19: from ZPublisher.HTTPResponse import HTTPResponse
20: from ZPublisher.BaseRequest import RequestContainer
21: import threading
22: import logging
23: import transaction
24: import copy
25: import codecs
26: import sys
27: from BTrees.IOBTree import IOBTree
28: import cdliSplitter
29: from sets import Set
30: import md5
31: from DownloadBasket import DownloadBasketFinallyThread
32: from types import *
33: import pickle
34: import tempfile
35: from cdli_files import CDLIFile
36: from cdli_files import splitatf,checkFile
37: from cdli_helpers import *
38:
39: class BasketContent(SimpleItem):
40: """classe fuer den Inhalt eines Baskets"""
41:
42: def getFileAndVersionFromId(self,pnum,versionNr):
43:
44: obj=self.cdliRoot.getFileObject(pnum)
45: logging.debug("obj : %s"%obj)
46: version=obj.getVersionNr(versionNr)
47: logging.debug("-------vs: %s"%version.getFileName())
48: return version,obj
49:
50: def __init__(self,content=[]):
51: """content"""
52:
53: self.setContent(content[0:])
54:
55: def getContent(self,filtered=True):
56: return self.contentList
57:
58: def getContentOld(self,filtered=True):
59: """get content"""
60: logging.debug("content object: content List %s"%self.contentList)
61: ret=[]
62:
63: return [self.getFileAndVersionFromId(x[0],x[1]) for x in self.contentList]
64: #
65: # if filtered:
66: # for x in self.contentList:
67: # if not((x[0] is None) or (x[1] is None)):
68: # ret.append(x)
69: # logging.debug("content object: content List -done filtered")
70: # return ret
71: #
72: # else:
73: # logging.debug("content object: content List -done not filtered")
74: # return self.contentList
75:
76: def allContent(self):
77: """get all content"""
78: return self.getContent(filtered=False)
79:
80: def setContent(self,content):
81: contentList=[]
82: for x in content:
83: if not((x[0] is None) or (x[1] is None)):
84: logging.debug("XXX"+str(x[0]))
85: logging.debug("YYY"+str(x[1]))
86:
87: #unterschiedliche versionen der Objekte, manchmal ein Objekt, manchmal die entprechenden werte
88: currentId=x[1]
89: if hasattr(currentId,'getId'):
90: currentId=x[1].getId()
91:
92: versionNumber=x[0]
93: if hasattr(versionNumber,'getVersionNumber'):
94: versionNumber=x[0].getVersionNumber()
95:
96:
97: logging.debug("XXX"+str(currentId))
98: logging.debug("YYY"+str(versionNumber))
99:
100: contentList.append((currentId,versionNumber))
101:
102: logging.debug("cl: %s"%contentList)
103: self.contentList=contentList[0:]
104:
105: def numberOfItems(self):
106: """number"""
107:
108: return len(self.getContent())
109:
110:
111: class uploadATFfinallyThread(Thread):
112: """class for adding uploaded filed (temporarily stored in the staging area at /tmp"""
113:
114: def __init__(self):
115: """init for uploadATFfinallyThread"""
116: self.continueVar=True
117: self.returnValue=None
118: self.end=False
119: Thread.__init__(self)
120:
121: def set(self,procedure,comment="",basketname='',unlock=None,SESSION=None,username=None,serverport="8080"):
122: """set start values for the thread"""
123: self.procedure=procedure
124: self.comment=comment
125: self.basketname=basketname
126: self.unlock=unlock
127: self.SESSION=SESSION
128: self.username=username
129: self.serverport=serverport
130:
131:
132: def __call__(self):
133: """call of the thread (equals run)"""
134: self.run()
135: return True
136:
137: def getContext(self, app,serverport="8080"):
138: """get the context within the ZODB"""
139:
140: resp = HTTPResponse(stdout=None)
141: env = {
142: 'SERVER_NAME':'localhost',
143: 'SERVER_PORT':serverport,
144: 'REQUEST_METHOD':'GET'
145: }
146: req = HTTPRequest(None, env, resp)
147: return app.__of__(RequestContainer(REQUEST = req))
148:
149:
150: def run(self):
151: """run"""
152:
153: self.result=""
154: #find context within ZODB
155: from Zope2 import DB
156: conn = DB.open()
157: root = conn.root()
158: app = root['Application']
159: ctx = self.getContext(app,serverport=self.serverport)
160:
161: #add the files
162: self.uploadATFfinallyThread(ctx,self.procedure,comment=self.comment,basketname=self.basketname,unlock=self.unlock,SESSION=self.SESSION,username=self.username)
163: #commit the transactions
164: transaction.get().commit()
165: conn.close()
166: #set flag for end of this method
167: self.end=True
168: logging.info("ended")
169: return True
170:
171: def __del__(self):
172: """delete"""
173:
174:
175:
176: def getResult(self):
177: """method for accessing result"""
178:
179: return self.result
180:
181: def uploadATFfinallyThread(self,ctx,procedure,comment="",basketname='',unlock=None,RESPONSE=None,SESSION=None,username=None):
182: """upload the files"""
183: #TODO: make this configurable, at the moment, rootFolder for cdli has to be cdliRoot
184: ctx2=ctx.cdliRoot
185:
186: self.result+="<h2>Start processing</h2>"
187:
188: #shall I only upload the changed files?
189: logging.debug("uploadATFfinally procedure: %s"%procedure)
190: if procedure=="uploadchanged":
191: changed=[x[0] for x in SESSION.get('changed',[])]
192: uploadFns=changed+SESSION.get('newPs',[])
193:
194: #or all
195: elif procedure=="uploadAll":
196: uploadFns=[]
197: for x in os.listdir(SESSION['tmpdir']):
198: if not x in SESSION['lockerrors']:
199: uploadFns.append(x)
200:
201: #or maybe nothing
202: elif procedure=="noupload":
203: return True
204: else:
205: uploadFns=[]
206:
207: #do first the changed files
208: i=0
209: for fn in uploadFns:
210: logging.debug("uploadATFfinally uploadFn=%s"%fn)
211: i+=1
212: founds=ctx2.CDLICatalog.search({'title':fn})
213: if len(founds)>0:
214: SESSION['author']=str(username)
215: self.result="<p>Changing : %s"%fn+self.result
216: logging.debug("uploadatffinallythread changing:%s"%fn+self.result)
217: founds[0].getObject().manage_addCDLIFileObject('',comment,SESSION['author'],file=os.path.join(SESSION['tmpdir'],fn),from_tmp=True)
218: if i%200==0:
219: transaction.get().commit()
220: logging.debug("uploadatffinallythread changing: do commit")
221:
222: transaction.get().commit()
223: logging.debug("uploadatffinallythread changing: last commit")
224:
225: #now add the new files
226: newPs=SESSION['newPs']
227: if len(newPs)>0:
228: tmpDir=SESSION['tmpdir']
229: logging.debug("uploadatffinallythread adding start")
230: self.result="<p>Adding files</p>"+self.result
231: #TODO: make this configurable, at the moment base folder for the files has to be cdli_main
232: ctx2.importFiles(comment=comment,author=str(username) ,folderName=tmpDir, files=newPs,ext=self)
233: logging.debug("uploadatffinallythread adding finished")
234:
235: #unlock locked files?
236: if unlock:
237: logging.debug("uploadatffinallythread unlocking start")
238: self.result="<p>Unlock files</p>"+self.result
239: unlockFns=[]
240: for x in os.listdir(SESSION['tmpdir']):
241: if not x in SESSION['errors']:
242: unlockFns.append(x)
243:
244: logging.debug("unlocking have now what to unlock")
245:
246: for fn in unlockFns:
247: #logging.info("will unlock: %s"%fn)
248: founds=ctx2.CDLICatalog.search({'title':fn})
249: #logging.info("found it: %s"%repr(founds))
250: if len(founds)>0:
251: #logging.info("unlock: %s"%founds[0].getObject().getId())
252: SESSION['author']=str(username)
253: founds[0].getObject().lockedBy=""
254:
255: logging.debug("uploadatffinallythread unlocking done")
256:
257: #if a basketname is given, add files to the basket
258: if not (basketname ==''):
259: logging.debug("uploadatffinallythread add to basket %s"%basketname)
260: self.result="<p>Add to basket</p>"+self.result
261: basketId=ctx2.basketContainer.getBasketIdfromName(basketname)
262:
263: if not basketId: # create new basket
264: logging.debug("uploadatffinallythread create basket %s"%basketname)
265: self.result="<p>Create a new basket</p>"+self.result
266: ob=ctx2.basketContainer.addBasket(basketname)
267: basketId=ob.getId()
268: basket=getattr(ctx2.basketContainer,str(basketId))
269: ids=os.listdir(SESSION['tmpdir'])
270: #logging.debug("should add:"+repr(ids))
271: basket.addObjects(ids,deleteOld=True,username=str(username))
272:
273: logging.debug("uploadatffinallythread uploadfinally done")
274:
275: if RESPONSE is not None:
276: RESPONSE.redirect(self.aq_parent.absolute_url())
277:
278: return True
279:
280: class tmpStore(SimpleItem):
281: """simple item"""
282: meta_type="cdli_upload"
283:
284: def __init__(self,id):
285: """init tmp"""
286: self.id=id
287:
288: class uploadATFThread(Thread):
289: """class for checking the files befor uploading"""
290:
291: def __init__(self):
292: """initialise"""
293:
294: self.continueVar=True
295: self.returnValue=None
296:
297: Thread.__init__(self)
298:
299:
300: def set(self,upload,basketId,username,idTmp,serverport="8080"):
301: """set start values for the thread"""
302: self.result=""
303: self.upload=upload
304: self.basketId=basketId
305: self.username=username
306: self.serverport=serverport
307: self.idTmp=idTmp
308:
309: def __call__(self):
310: """call method """
311: self.run()
312: return True
313:
314: def getContext(self, app,serverport="8080"):
315: """get the context within the ZODB"""
316: resp = HTTPResponse(stdout=None)
317: env = {
318: 'SERVER_NAME':'localhost',
319: 'SERVER_PORT':serverport,
320: 'REQUEST_METHOD':'GET'
321: }
322: req = HTTPRequest(None, env, resp)
323: return app.__of__(RequestContainer(REQUEST = req))
324:
325: def run(self):
326: idTmp=self.idTmp
327: self.result=""
328: #find context within ZODB
329: from Zope2 import DB
330: conn = DB.open()
331: root = conn.root()
332: app = root['Application']
333: ctx = self.getContext(app,serverport=self.serverport)
334: logging.info("run intern")
335: try:
336: logging.info("created: %s"%idTmp)
337: ctx.temp_folder._setObject(idTmp,tmpStore(idTmp))
338: except:
339: logging.error("thread upload: %s %s"%sys.exc_info()[0:2])
340:
341: logging.info("call thread intern")
342: self.uploadATFThread(ctx,self.upload,idTmp,self.basketId)
343:
344: #ctx.cdliRoot.cdli_main.tmpStore2[self.getName()[0:]]=self.returnValue
345:
346:
347: transaction.get().commit()
348:
349: conn.close()
350:
351: return getattr(ctx.temp_folder,idTmp)
352:
353: def getResult(self):
354: """method for accessing result"""
355: return self.result
356:
357: def uploadATFThread(self,ctx,upload,idTmp,basketId=0):
358: """upload an atf file"""
359: #TODO: add comments
360: #TODO: finish uploadATF
361:
362: stObj=getattr(ctx.temp_folder,idTmp)
363: logging.info("start, upload thread")
364: self.result="<html><body><h2>I got your file, start now to split it into single atf-files!</h2><p>"
365:
366: #make sure that id is a string and not an integer
367: basketId=str(basketId)
368: logging.info("basketID:"+basketId)
369: #TODO: make this configurable, at the moment, rootFolder for cdli has to be cdliRoot
370: ctx2=ctx.cdliRoot
371:
372: #get temporary file for staging the downloaded and splitted files
373: dir=tempfile.mkdtemp()
374:
375: logging.info("tmpfFile:"+str(dir))
376: changed=[] # changed files
377: errors=[] # files with errors
378: lockerrors=[] # files with errors
379:
380: newPs=[] # new p filed
381: psNotInCatalog=[] # files not in the catalog
382:
383: #split the uploadedd atf file
384: logging.info("start splitting")
385: basketNameFromFile, numberOfFiles=splitatf(upload,dir,ext=self)
386:
387: #find basketId if not set
388:
389: #get active abaket
390: if basketId == '0':
391: basketObj=ctx2.basketContainer.getActiveBasket()
392: if basketObj:
393: basketId=basketObj.getId()
394:
395: #if there is no active basket and no basketid given, id is empty, else get besketname and length
396: if basketId == '0':
397: basketNameFromId=""
398: basketLen=0
399: else:
400: basketNameFromId=getattr(ctx2.basketContainer,basketId).title
401: basketLen=getattr(ctx2.basketContainer,basketId).getLastVersion().numberOfItems()
402:
403: logging.info("got the file, upload thread")
404: self.result+="""<html><body><h2>I got the files</h2><
405: p>I am computing the differences to the exisiting files</p>"""
406:
407: #start to check the files
408: for fn in os.listdir(dir):
409:
410: self.result="<p>process:%s</p>"%fn+self.result
411:
412: # check if file is in the catalog
413: #TODO: checkCatalog is not implemented yet
414: if ctx2.cdli_main.checkCatalog(fn):
415: psNotInCatalog.append(fn)
416:
417: #check if p-file already at the server
418: founds=ctx2.CDLICatalog.search({'title':fn})
419:
420: #if not than add filename to the list of newfiles
421:
422: data=file(os.path.join(dir,fn)).read()
423: status,msg=checkFile(fn,data,dir)
424: #status=True
425:
426:
427: if not status: # error
428: errors.append((fn,msg))
429:
430: else:
431: if len(founds)==0:
432: newPs.append(fn)
433:
434: #if p file alread at the server
435: for found in founds:
436: #analyse the differences to the actual file
437: obj=found.getObject()
438:
439: if (not (str(obj.lockedBy))=='') and (not (str(obj.lockedBy)==str(self.username))):
440: lockerrors.append((fn,str(obj.lockedBy)))
441: else:
442:
443: diffs=obj.diff(data)
444: if diffs[0]>0:
445: changed.append((obj,diffs)) #hochladen
446:
447: #ready, set the returnValues
448: self.result+="<h3>Done</h3></body></html>"
449:
450: stObj.returnValue={}
451:
452: stObj.returnValue['errors']=errors
453:
454: stObj.returnValue['newPs']=newPs
455: stObj.returnValue['tmpdir']=dir
456: stObj.returnValue['basketLen']=basketLen
457: stObj.returnValue['numberOfFiles']=numberOfFiles
458: stObj.returnValue['basketNameFromId']=basketNameFromId
459: stObj.returnValue['basketNameFromFile']=basketNameFromFile
460: stObj.returnValue['basketId']=basketId
461: stObj.returnValue['dir']=dir
462: #stObj.returnValue['changed']=copy.copy(changed)
463: stObj.returnValue['changed']=[(x[0].getId(),x[1][0]) for x in changed]
464: #stObj.returnValue['lockerrors']=[x[0].getId() for x in lockerrors]
465: stObj.returnValue['lockerrors']=[x for x in lockerrors]
466: self.returnValue=True
467: #ctx2.cdli_main.setTemp('v_uploadATF_returnValue',True)
468:
469: class CDLIBasketContainer(OrderedFolder):
470: """contains the baskets"""
471:
472:
473: security=ClassSecurityInfo()
474: meta_type="CDLIBasketContainer"
475:
476: def getResultHash(self):
477: """get the result hash for debug purposes"""
478: return self.resultHash.keys()
479:
480: def getPNumbersOfBasket(self,basketName):
481: """get all pnumbers of a basket as a list, returns an empty list if basket not found
482: @param basketName: name of the basket
483: """
484: ret=[]
485: basketId=self.getBasketIdfromName(basketName)
486: if not basketId:
487: return []
488:
489: ob=getattr(self,basketId).getContent() #get the content of a basket
490:
491: ret=[x[0].split(".")[0] for x in ob]
492:
493: return ret
494:
495: security.declareProtected('manage','getBasketAsOneFile')
496: def getBasketAsOneFile(self,basketName,current="no"):
497: """returns all files of the basket combined in one file
498: @param basketName: Name of the basket
499: @param current: (optional) if current is set to "yes" then the most current version of
500: all files are downloaded and not the versions of the files as stored in the basket
501: """
502: ret=""
503: basketId=self.getBasketIdfromName(basketName)
504: if not basketId:
505: return ""
506:
507: ob=getattr(self,basketId).getLastVersion()
508: for pnum,versionNr in ob.getContent():
509: obj=self.cdliRoot.getFileObject(pnum)
510: # logging.debug("obj : %s"%obj)
511: # version=obj.getVersionNr(versionNr)
512:
513: if current=="no": #version as they are in the basket
514: cur= obj.getVersionNr(versionNr)
515: ret+=str(cur.getData())+"\n"
516: elif current=="yes":
517: #search current object
518: #logging.debug("current: %s"%object[1].getId().split(".")[0])
519: obj.getData()
520: return ret
521:
522: security.declareProtected('manage','upDateBaskets')
523: def upDateBaskets(self):
524: """update content in to objects"""
525:
526: founds=self.ZopeFind(self,obj_metatypes=['CDLIBasketVersion'],search_sub=1)
527:
528: for found in founds:
529: found[1].updateBasket()
530:
531: security.declareProtected('manage','deleteBaskets')
532: def deleteBaskets(self,ids=None):
533: """delete baskets, i.e. move them into trash folder"""
534:
535: if ids is None:
536: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','cdliError_html.zpt')).__of__(self)
537: txt="Sorry, no basket selected!"
538: return pt(txt=txt)
539:
540: found=self.ZopeFind(self,obj_ids=['trash'])
541:
542: if len(found)<1:
543: manage_addFolder(self, 'trash')
544: trash=self._getOb('trash')
545: else:
546: trash=found[0][1]
547:
548: if type(ids) is not ListType:
549: ids=[ids]
550: logging.error("XERXON:"+repr(ids))
551: if len(ids)==0:
552: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','cdliError_html.zpt')).__of__(self)
553: txt="Sorry, no basket selected!"
554: return pt(txt=txt)
555:
556: cut=self.manage_cutObjects(ids)
557: trash.manage_pasteObjects(cut)
558: return None
559: security.declareProtected('manage','manageBaskets')
560: def manageBaskets(self,submit,ids=None,basket1="",basket2="",joinBasket="",subtractBasket="",REQUEST=None,RESPONSE=None):
561: """manage baskets, delete or copy"""
562: if submit=="delete":
563: ret= self.deleteBaskets(ids)
564: if ret:
565: return ret
566: elif submit=="join":
567: flag,msg=self.joinBasket(joinBasket, ids)
568: logging.info("joining %s %s"%(flag,msg))
569: if not flag:
570: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','cdliError_html.zpt')).__of__(self)
571:
572: return pt(txt=msg)
573:
574: elif submit=="subtract":
575: logging.info("BBBb %s %s"%(basket1,basket2))
576: flag,msg=self.subtractBasket(subtractBasket, basket1,basket2)
577: logging.info("subtract %s %s"%(flag,msg))
578:
579: if RESPONSE:
580: RESPONSE.redirect(self.absolute_url())
581:
582: security.declareProtected('View','getBasketIdfromName')
583: def getBasketIdfromName(self,basketname):
584: """get id from name"""
585:
586: for basket in self.ZopeFind(self,obj_metatypes=["CDLIBasket"]):
587: if basket[1].title==basketname:
588: return basket[0]
589: else:
590: None
591:
592: security.declareProtected('manage','uploadBasket_html')
593:
594: def uploadBasketAsync_html(self,basketId='0'):
595: """upload an atf file, html form, jetzt aufruf der nicht asyncronen version mit ticktes"""
596:
597:
598: basketId=str(basketId)
599: if not basketId=='0':
600: basketName=getattr(self.basketContainer,basketId).title
601: else:
602: basketName=""
603:
604: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadBasketAsync_html.zpt')).__of__(self)
605: return pt(basketId=basketId,basketName=basketName)
606:
607:
608:
609: def uploadBasket_html(self,basketId='0'):
610: """upload an atf file, html form"""
611:
612:
613: basketId=str(basketId)
614: if not basketId=='0':
615: basketName=getattr(self.basketContainer,basketId).title
616: else:
617: basketName=""
618:
619: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','uploadBasket_html.zpt')).__of__(self)
620: return pt(basketId=basketId,basketName=basketName)
621:
622:
623: security.declareProtected('manage','index_html')
624: def index_html(self):
625: """stanadard ansicht"""
626:
627:
628:
629: ext=self.ZopeFind(self,obj_ids=["index.html"])
630: if ext:
631: return ext[0][1]()
632:
633: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','BasketContainerMain')).__of__(self)
634: return pt()
635:
636: def getStorageFolderRoot(self):
637: """root des storage folders"""
638: return self.cdli_main
639:
640: def __init__(self,id,title):
641: """ init basket container"""
642: self.id=id
643: self.title=title
644:
645:
646: def getBasketsId(self):
647: """get all baskets als klartext"""
648:
649: ret=""
650: baskets=self.ZopeFind(self,obj_metatypes=['CDLIBasket'])
651: for basket in baskets:
652: com,user,time,values = basket[1].getContentIds()
653: ret+= "BASKET:"+com+"\t"+user+"\t"+time+"\n"
654: for x in values:
655: ret+= x[0]+"\t"+x[1]+"\n"
656: return ret
657:
658: def getBaskets(self,sortField='title'):
659: """get all baskets files"""
660:
661: def sortName(x,y):
662: return cmp(x[1].title.lower(),y[1].title.lower())
663:
664: def sortDate(x,y):
665: return cmp(y[1].getLastVersion().getTime(),x[1].getLastVersion().getTime())
666:
667:
668: def sortComment(x,y):
669:
670:
671:
672: try:
673: xc=getattr(x[1],'comment','ZZZZZZZZZZZZZ').lower()
674: except:
675: xc='ZZZZZZZZZZZZZ'.lower()
676: try:
677: yc=getattr(y[1],'comment','ZZZZZZZZZZZZZ').lower()
678: except:
679: yc='ZZZZZZZZZZZZZ'.lower()
680:
681:
682: if (xc=='') or (xc=='ZZZZZZZZZZZZZ'.lower()):
683:
684: try:
685: xc=x[1].getLastVersion().getComment().lower()
686: except:
687: xc='ZZZZZZZZZZZZZ'.lower()
688:
689: if (yc=='') or (yc=='ZZZZZZZZZZZZZ'.lower()):
690: try:
691: yc=y[1].getLastVersion().getComment().lower()
692: except:
693: yc='ZZZZZZZZZZZZZ'.lower()
694:
695:
696: return cmp(xc,yc)
697:
698: def sortAuthor(x,y):
699:
700: return cmp(x[1].getLastVersion().getUser().lower(),y[1].getLastVersion().getUser().lower())
701:
702: baskets=self.ZopeFind(self,obj_metatypes=['CDLIBasket'])
703:
704:
705: if sortField=='title':
706: baskets.sort(sortName)
707: elif sortField=='date':
708: baskets.sort(sortDate)
709: elif sortField=='author':
710: baskets.sort(sortAuthor)
711: elif sortField=='comment':
712: baskets.sort(sortComment)
713:
714: return baskets
715:
716:
717: def subtractBasket(self,newBasket,basket1,basket2):
718: """subtract basket2 from basket1
719: (i.e. newbasket will contain alle elements of basket1 which are not in basket2),
720: if basket2 contains files which are not in basket1, then theses files fill be ignored
721:
722: @param newbasket: name of the new basket
723: @param basket1: basket where basket2 will be subtracted from
724: @param basket2: see above
725:
726: """
727:
728: logging.info("CCCCC %s %s"%(basket1,basket2))
729:
730: try:
731: newB=self.addBasket(newBasket)
732: except:
733: return False, "cannot create the new basket"
734:
735:
736:
737:
738:
739: bas2= getattr(self,basket2)
740: bas2content=bas2.getContent()
741: bas2ids=[x[0] for x in bas2content]
742:
743:
744:
745: bas1= getattr(self,basket1)
746: bas1content=bas1.getContent()
747:
748:
749: newBasketContent={}
750:
751: for id,version in bas1content:
752: if not (id in bas2ids):
753: newBasketContent[id]=version
754:
755: username=self.getActualUserName()
756:
757: logging.info("sbc %s"%newBasketContent)
758: newB.addObjectsWithVersion(newBasketContent,username=username,catalog=self.CDLICatalog)
759:
760: return True, ""
761:
762:
763: def joinBasket(self,newBasket,oldBaskets):
764: """join two baskets
765: @param newbasket: name of the new basket
766: @param oldbaskets: list of baskets to be joined
767: """
768: if oldBaskets is None:
769: return False, "No Baskets selected!"
770:
771: try:
772: newB=self.addBasket(newBasket)
773: except:
774: return False, "cannot create the new basket"
775:
776: newBasketContent={}
777:
778: for ob in oldBaskets:
779: x= getattr(self,ob,None)
780: if x is None:
781: return False, "cannot find basket: %s"%ob
782:
783: ids=x.getContent() # hole den Inhalt
784:
785: for id,version in ids:
786: if newBasketContent.has_key(id): # p number gibt's schon
787: newBasketContent[id]=max(newBasketContent[id],version) # speichere die groessere Versionsnumber
788: else:
789: newBasketContent[id]=version
790: username=self.getActualUserName()
791:
792: logging.info("nbc %s"%newBasketContent)
793: newB.addObjectsWithVersion(newBasketContent,username=username,catalog=self.CDLICatalog)
794:
795: return True, ""
796:
797: def getNewId(self):
798: """createIds"""
799: last=getattr(self,'last',0)
800: last +=1
801: while len(self.ZopeFind(self,obj_ids=[str(last)]))>0:
802: last+=1
803:
804: self.last=last
805: return last
806:
807: def setActiveBasket(self,basketId,REQUEST=None):
808: """store active basketId in a cookie"""
809: self.REQUEST.RESPONSE.setCookie("CDLIActiveBasket",basketId,path="/")
810: try:
811: qs=cgi.parse_qs(REQUEST['QUERY_STRING'])
812: del(qs['basketId'])
813: except:
814: qs={}
815: if REQUEST:
816: REQUEST.RESPONSE.redirect(REQUEST['URL1']+'?'+urllib.urlencode(qs))
817:
818: def getActiveBasket(self):
819: """get active basket from cookie"""
820:
821: id= self.REQUEST.cookies.get('CDLIActiveBasket',None)
822: if id:
823: obj=getattr(self,str(id),None)
824: else:
825: obj=None
826: return obj
827:
828: def getActualUserName(self):
829: """get name of the actualuser"""
830: return str(self.REQUEST['AUTHENTICATED_USER'])
831:
832: security.declareProtected('manage','addBasket')
833: def addBasket(self,newBasketName):
834: """add a new basket"""
835:
836: ob=manage_addCDLIBasket(self,newBasketName)
837: return ob
838:
839: def storeInBasket(self,submit,ids=None,newBasketName=None,fromFileList=None,RESPONSE=None,REQUEST=None):
840: """store it"""
841: if not ids:
842: ids=self.REQUEST.SESSION['fileIds']
843:
844: if (type(ids) is not ListType) and (not isinstance(ids,Set)):
845: ids=[ids]
846:
847: if isinstance(ids,Set):
848: ids=list(ids)
849:
850: if (submit.lower()=="store in new basket") or (submit.lower()=="new basket"):
851: basketRet=self.addBasket(newBasketName)
852: self.setActiveBasket(basketRet.getId())
853: basket=getattr(self,basketRet.getId())
854: elif (submit.lower()=="store in active basket") or (submit.lower()=="active basket"):
855: basket=self.getActiveBasket()
856:
857: added=basket.addObjects(ids)
858: back=self.REQUEST['HTTP_REFERER'].split("?")[0]+"?basketName="+basket.title+"&numberOfObjects="+str(added)
859:
860:
861: if fromFileList:
862:
863: return self.cdli_main.findObjectsFromList(list=ids,basketName=basket.title,numberOfObjects=added)
864:
865: if RESPONSE:
866:
867: RESPONSE.redirect(back)
868:
869: return True
870:
871: def manage_addCDLIBasketContainerForm(self):
872: """add the CDLIBasketContainer form"""
873: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addCDLIBasketContainer.zpt')).__of__(self)
874: return pt()
875:
876: def manage_addCDLIBasketContainer(self,id,title,RESPONSE=None):
877: """add the basket"""
878: ob=CDLIBasketContainer(id,title)
879:
880: self._setObject(id, ob)
881:
882: if RESPONSE is not None:
883: RESPONSE.redirect('manage_main')
884:
885: class CDLIBasket(Folder,CatalogAware):
886: """basket"""
887:
888: meta_type="CDLIBasket"
889: default_catalog="CDLIBasketCatalog"
890:
891: def searchInBasket(self,indexName,searchStr,regExp=False):
892: """searchInBasket"""
893:
894: lst=self.searchInLineIndexDocs(indexName,searchStr,uniq=True,regExp=regExp) #TODO: fix this
895: ret={}
896:
897: lv=self.getLastVersion()
898:
899:
900: for obj in lv.content.getContent():
901: id=obj[1].getId().split(".")[0]
902: if id in lst:
903:
904: ret[id]=self.showWordInFile(id,searchStr,lineList=self.getLinesFromIndex(indexName,searchStr,id,regExp=regExp),regExp=regExp,indexName=indexName)
905:
906:
907: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','searchResultsInBasket')).__of__(self)
908: return pt(result=ret,indexName=indexName,regExp=regExp,word=searchStr)
909:
910:
911:
912:
913: def searchInBasket_v1(self,searchStr):
914: """search occurences of searchStr in files im basket"""
915: ret=[]
916: lv=self.getLastVersion()
917: logging.info("searching")
918: for obj in lv.content.getContent():
919: txt=obj[0].getData()
920: for x in txt.split("\n"):
921: logging.info("search %s"%x)
922: if re.match(searchStr,x):
923: ret.append(x)
924:
925: return "\n".join(ret)
926:
927:
928: def getFile(self,obj):
929: return obj[1]
930:
931: def getFileLastVersion(self,obj):
932: return obj[0]
933:
934: def getFileNamesInLastVersion(self):
935: """get content of the last version as list"""
936:
937: return [x[1].getId() for x in self.getLastVersion().getContent()]
938:
939:
940: def isActual(self,obj,nummer):
941: """teste ob im basket die aktuelle version ist, obj kann entweder ein CDLIFile sein oder eine
942: eine pnummer, die auf ein CDLIFile verweist"""
943: try:
944: #logging.debug("isActual:"+repr(obj))
945: if isinstance(obj, CDLIFile):
946: actualNo=obj.getLastVersion().getVersionNumber()
947: else:
948: actualNo=self.cdliRoot.getFileObjectLastVersion(obj).getVersionNumber()
949:
950: if actualNo==nummer:
951: return True , 0
952: else:
953: return False, actualNo
954: except:
955: logging.error( """is actual: %s (%s %s)"""%(repr(obj),sys.exc_info()[0],sys.exc_info()[1]))
956: logging.error(""" PARAMS: %s %s"""%(obj,nummer))
957: return False, -1
958: def isActualOld(self,obj):
959: """teste ob im basket die aktuelle version ist"""
960: try:
961: #logging.debug("isActual:"+repr(obj))
962: actualNo=obj[1].getLastVersion().getVersionNumber()
963: storedNo=obj[0].getVersionNumber()
964:
965:
966: #actualNo=self.getFileObjectLastVersion(obj.getId()).getVersionNumber()
967:
968: #if len(founds)>0 and founds[0].getObject().aq_parent.getId()==".trash":
969: # return False, -1
970:
971: if actualNo==storedNo:
972: return True , 0
973: else:
974: return False, actualNo
975: except:
976: logging.error( """is actual: %s (%s %s)"""%(repr(obj),sys.exc_info()[0],sys.exc_info()[1]))
977:
978: return False, -1
979:
980: def history(self):
981: """history"""
982:
983: ext=self.ZopeFind(self.aq_parent,obj_ids=["history_template.html"])
984: if ext:
985: return getattr(self,ext[0][1].getId())()
986:
987: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','BasketHistory')).__of__(self)
988: return pt()
989:
990: def getStorageFolderRoot(self):
991: """root des storage folders"""
992: return self.aq_parent.cdli_main
993:
994: def __init__(self,id,title,shortDescription="",comment=""):
995: """init a CDLIBasket"""
996:
997: self.id=id
998: self.title=title
999: self.shortDescription=shortDescription
1000: self.comment=comment
1001:
1002: def getActualUserName(self):
1003: """get name of the actualuser"""
1004:
1005: return str(self.REQUEST['AUTHENTICATED_USER'])
1006:
1007:
1008: def getLastVersion(self):
1009: """hole letzte version"""
1010:
1011: ids=[]
1012: idsTmp= self.objectIds()
1013: for x in idsTmp:
1014: try:
1015: ids.append(int(x))
1016: except:
1017: pass
1018: ids.sort()
1019:
1020: if len(ids)==0:
1021: return None
1022: else:
1023: ob=getattr(self,str(ids[-1]))
1024:
1025:
1026: return ob
1027:
1028: def getVersions(self):
1029: """get versions"""
1030: versions=self.ZopeFind(self,obj_metatypes=["CDLIBasketVersion"])
1031: return versions
1032:
1033:
1034: def updateObjects(self,ids,RESPONSE=None,REQUEST=None):
1035: """update ids, ids not in the basket the add"""
1036: if type(ids) is not ListType:
1037: ids=[ids]
1038:
1039: lastVersion=self.getLastVersion()
1040: oldContent=lastVersion.content.getContent()
1041: newContent=[]
1042:
1043: #first copy the old
1044: for obj in oldContent:
1045: currentId=obj[1]
1046: if hasattr(currentId,'getId'):
1047: currentId=obj[1].getId()
1048:
1049: if currentId not in ids:
1050: newContent.append(obj)
1051: #now add the new
1052:
1053: for id in ids:
1054: founds=self.CDLICatalog.search({'title':id})
1055:
1056: for found in founds:
1057: if found.getObject() not in oldContent:
1058: #TODO: was passiert wenn, man eine Object dazufuegt, das schon da ist aber eine neuere version
1059: newContent.append((found.getObject().getLastVersion(),found.getObject()))
1060:
1061:
1062: content=newContent
1063: user=self.getActualUserName()
1064:
1065: ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=newContent)
1066:
1067: obj=self._getOb(ob.getId())
1068: if RESPONSE:
1069:
1070: RESPONSE.redirect(obj.absolute_url())
1071:
1072: return obj
1073:
1074: def addObjectsWithVersion(self,ids,deleteOld=None,username=None,catalog=None):
1075: """generate a new version of the basket with objects added,
1076: hier wird jedoch nicht die letzte Version jedes Files hinzugefuegt, s
1077: ondern ids is ein Tupel mit der Id (d.h. der p-number) und der Versionsnummer.
1078: """
1079: logging.info("add to basket (%s)"%(self.getId()))
1080: lastVersion=self.getLastVersion()
1081:
1082: if not catalog:
1083: catalog=self.CDLICatalog
1084:
1085: if lastVersion is None:
1086: oldContent=[]
1087: else:
1088: oldContent=lastVersion.content.getContent()
1089:
1090: if deleteOld:
1091: oldContent=[]
1092:
1093: newContent=[]
1094: added=0
1095:
1096: for id,version in ids.iteritems():
1097: logging.info("adding %s %s"%(id,version))
1098: id=id.split(".")[0] # title nur die pnumber ohne atf
1099:
1100: try:
1101: founds=catalog.search({'title':id})
1102: except:
1103: founds=[]
1104: logging.info(" found %s "%(founds))
1105: for found in founds:
1106: if found.getObject() not in oldContent:
1107:
1108: #TODO: was passiert wenn, man eine Object dazufuegt, das schon da ist aber eine neuere version
1109: newContent.append((found.getObject().getVersions()[version-1][1],found.getObject()))
1110: added+=1
1111:
1112: content=oldContent+newContent
1113: if not username:
1114: logging.error("XXXXXXXXXXX %s"%repr(self))
1115: user=self.getActualUserName()
1116: else:
1117: user = username
1118:
1119: ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=content)
1120: logging.info("add to basket (%s) done"%(self.getId()))
1121: return added
1122:
1123:
1124: def addObjects(self,ids,deleteOld=None,username=None):
1125: """generate a new version of the basket with objects added"""
1126:
1127: def swap(x):
1128: return (x[1],x[0])
1129:
1130: logging.info("add to basket (%s)"%(repr(ids)))
1131: logging.info("add to basket (%s)"%(self.getId()))
1132: lastVersion=self.getLastVersion()
1133:
1134: if lastVersion is None:
1135: oldContent=[]
1136: else:
1137: oldContent=lastVersion.content.getContent()
1138:
1139: if deleteOld:
1140: oldContent=[]
1141:
1142: added=0
1143: # for id in ids:
1144: # logging.debug("adding:"+id)
1145: # try:
1146: # founds=self.CDLICatalog.search({'title':id})
1147: # except:
1148: # founds=[]
1149: #
1150: # for found in founds:
1151: # if found.getObject() not in oldContent:
1152: # #TODO: was passiert wenn, man eine Object dazufugt, das schon da ist aber eine neuere version
1153: # newContent.append((found.getObject().getLastVersion(),found.getObject()))
1154: # added+=1
1155:
1156: hash = md5.new(repr(makelist(ids))).hexdigest() # erzeuge hash als identification
1157: #logging.debug("JJJJJJJ:"+repr(self.makelist(ids)))
1158:
1159: retrieved = self.CDLICache.retrieve(hash)
1160: if retrieved:
1161: logging.debug("add Objects: retrieved")
1162: newContent=Set(map(swap,retrieved))
1163: else:
1164: logging.debug("add Objects: new")
1165: newContent=Set([(self.getFileObjectLastVersion(x),self.getFileObject(x)) for x in ids])
1166:
1167:
1168:
1169: #remove all Elements which are not stored
1170: if (None,None) in newContent:
1171: newContent.remove((None,None))
1172: content=Set(oldContent).union(newContent)
1173: added = len(content)-len(oldContent)
1174: if not username:
1175: user=self.getActualUserName()
1176: else:
1177: user = username
1178:
1179: #logging.debug("content:"+repr(list(content)))
1180: ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=list(content))
1181: logging.info("add to basket (%s) done"%(self.getId()))
1182: return added
1183:
1184:
1185:
1186: def getContent(self):
1187: """print content"""
1188: ret=[]
1189:
1190: lv=self.getLastVersion()
1191: #for obj in lv.content.getContent():
1192: #logging.info("XXXXXXXXXX %s"%repr(obj))
1193: # ret.append((obj[1].getId(),obj[0].versionNumber))
1194:
1195: return lv
1196:
1197: def getContentIds(self):
1198: """print basket content"""
1199: ret=[]
1200: lv=self.getLastVersion()
1201: for obj in lv.content.getContent():
1202: ret.append((obj[0].getId(),obj[1].getId()))
1203:
1204:
1205: return lv.getComment(),lv.getUser(),lv.getTime(),ret
1206:
1207: def changeBasket(self,ids,submit,RESPONSE=None,REQUEST=None):
1208: """change a basket"""
1209: if submit=="update":
1210: self.updateObjects(ids,RESPONSE=RESPONSE,REQUEST=REQUEST)
1211: elif submit=="delete":
1212: self.deleteObjects(ids,RESPONSE=RESPONSE,REQUEST=REQUEST)
1213:
1214: def deleteObjects(self,ids,RESPONSE=None,REQUEST=None):
1215: """delete objects"""
1216:
1217: if type(ids) is not ListType:
1218: ids=[ids]
1219:
1220: lastVersion=self.getLastVersion()
1221: oldContent=lastVersion.content.getContent()
1222: newContent=[]
1223: for obj in oldContent:
1224: if obj[1].getId() not in ids:
1225: newContent.append(obj)
1226:
1227:
1228: user=self.getActualUserName()
1229:
1230: ob=manage_addCDLIBasketVersion(self,user,comment="",basketContent=newContent)
1231:
1232: if RESPONSE:
1233: obj=self._getOb(ob.getId())
1234: RESPONSE.redirect(obj.absolute_url())
1235:
1236: def manage_addCDLIBasketForm(self):
1237: """add the CDLIBasketContainer form"""
1238: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addCDLIBasket.zpt')).__of__(self)
1239: return pt()
1240:
1241: def manage_addCDLIBasket(self,title,shortDescription="",comment="",RESPONSE=None):
1242: """add the basket"""
1243:
1244: id=str(self.getNewId())
1245:
1246: ob=CDLIBasket(id,title,shortDescription,comment)
1247:
1248: self._setObject(id, ob)
1249:
1250: if RESPONSE is not None:
1251: RESPONSE.redirect('manage_main')
1252: else:
1253: return ob
1254:
1255:
1256:
1257: class CDLIBasketVersion(Implicit,Persistent,Folder):
1258: """version of a basket"""
1259:
1260: meta_type="CDLIBasketVersion"
1261: security=ClassSecurityInfo()
1262:
1263: def updateBasket(self):
1264: """update"""
1265: try:
1266: self._setObject('content',BasketContent(self.basketContent))
1267: except:
1268: try:
1269: if len(self.basketContent)>0:
1270: self.content.setContent(self.basketContent)
1271: except:
1272: print "error",self.getId(),self.aq_parent.getId()
1273: self.basketContent=[]
1274:
1275:
1276: def containsNonActualFiles(self):
1277: """returns True if basket contains one or more non current files"""
1278:
1279: objs=self.getContent()
1280: for obj in objs:
1281: if not self.isActual(obj[0],obj[1])[0]:
1282: return True
1283: return False
1284:
1285: def downloadListOfPnumbers(self):
1286: """download pnumbers of the basket as list"""
1287:
1288: basket_name=self.aq_parent.title
1289:
1290: ids=self.getContent() # get the list of objects
1291: logging.error(ids)
1292: ret="\n".join([x[1].getId().split(".")[0] for x in ids])
1293:
1294: self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename="%s.txt" """%basket_name)
1295: self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
1296: length=len(ret)
1297: self.REQUEST.RESPONSE.setHeader("Content-Length",length)
1298: self.REQUEST.RESPONSE.write(ret)
1299:
1300: security.declareProtected('manage','downloadObjectsAsOneFile')
1301: def downloadObjectsAsOneFile(self,lock=None,procedure=None,REQUEST=None,check="yes",current="no"):
1302: """download all selected files in one file"""
1303:
1304: if self.temp_folder.downloadCounterBaskets > 10000:
1305: return """I am sorry, currently the server has to many requests for downloads, please come back later!"""
1306:
1307:
1308: #if (check=="yes") and self.containsNonActualFiles():
1309: # pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadObjectAsOneFile_check.zpt')).__of__(self)
1310: #
1311: # return pt(lock=lock)
1312:
1313: # neue Version aus Performancegruenden, es wird nicht mehr getestet, ob es nicht aktuelle Objekte gibt
1314: # sondern lediglich gefragt.
1315: if (check=="yes"):
1316: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadObjectAsOneFile_ask.zpt')).__of__(self)
1317:
1318: return pt(lock=lock)
1319:
1320: else:
1321:
1322: return self.downloadObjectsAsOneFileFinally(lock=lock,procedure=procedure,REQUEST=REQUEST,current="no")
1323:
1324: def downloadObjectsAsOneFileFinally(self,lock=None,procedure=None,REQUEST=None,current="no",repeat=None):
1325: """print do the download"""
1326:
1327:
1328: ret=""
1329: lockedObjects={}
1330:
1331:
1332:
1333: if lock:
1334: logging.debug("------lock:"+repr(lock))
1335: if str(self.REQUEST['AUTHENTICATED_USER'])=='Anonymous User':
1336:
1337: return "please login first"
1338:
1339: #check if a locked object exist in the basket.
1340: lockedObjects={}
1341: for object in self.content.getContent():
1342: obj=self.getFileObject(object[0])
1343: if (not str(obj.lockedBy)=="") and (not (str(obj.lockedBy)==str(self.REQUEST['AUTHENTICATED_USER']))):
1344: lockedObjects[obj.title]=repr(obj.lockedBy)
1345:
1346:
1347: keys=lockedObjects.keys()
1348:
1349:
1350: if len(keys)>0 and (not procedure):
1351: self.REQUEST.SESSION['lockedObjects']=lockedObjects
1352: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','lockedObjects.zpt')).__of__(self)
1353:
1354:
1355: return pt()
1356:
1357: elif not procedure: #keine fails gesperrt dann alle donwloaden
1358: procedure="downloadAll"
1359:
1360:
1361:
1362:
1363: threadName=repeat
1364: if not threadName or threadName=="":
1365: thread=DownloadBasketFinallyThread()
1366: threadName=thread.getName()[0:]
1367:
1368: if (not hasattr(self,'_v_downloadBasket')):
1369: self._v_downloadBasket={}
1370:
1371:
1372: self._v_downloadBasket[threadName]=thread
1373: logging.debug("dwonloadfinally:"+repr(self))
1374:
1375: if isinstance(self,CDLIBasketVersion):
1376: obj=self
1377: else:
1378: obj=self.aq_parent
1379: logging.debug("dwonloadfinally2:"+repr(obj))
1380: logging.debug("dwonloadfinally2:"+repr(obj.aq_parent))
1381:
1382: obj2=obj.aq_parent
1383: if not isinstance(obj2,CDLIBasket):
1384: obj2=obj2.aq_parent
1385:
1386: basketID=obj2.getId()
1387: versionNumber=obj.getId()
1388: logging.debug("dwonloadfinally2:"+repr(basketID))
1389: logging.debug("dwonloadfinally2:"+repr(versionNumber))
1390:
1391:
1392: if lock:
1393: logging.debug("-----start locking")
1394: for object in self.content.getContent():
1395: obj=self.getFileObject(object[0])
1396: if obj.lockedBy =='':
1397: obj.lockedBy=self.REQUEST['AUTHENTICATED_USER']
1398: logging.debug("-----finished locking")
1399:
1400: #obj.lockedBy=user
1401: self._v_downloadBasket[threadName].set(lock,procedure,self.REQUEST['AUTHENTICATED_USER'],current,basketID,versionNumber)
1402:
1403: self._v_downloadBasket[threadName].start()
1404:
1405:
1406:
1407: wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
1408:
1409: if wait_template:
1410: return wait_template[0][1]()
1411: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadBasketWait.zpt')).__of__(self)
1412:
1413: return pt(txt=self.absolute_url()+'/downloadObjectsAsOneFileFinally',threadName=threadName,
1414: counter=self._v_downloadBasket[threadName].getCounter(),
1415: number=self._v_downloadBasket[threadName].getNumberOfFiles())
1416: #_v_xmltrans.run()
1417:
1418: else:
1419: #recover thread, if lost
1420: if not hasattr(self,'_v_downloadBasket'):
1421: self._v_downloadBasket={}
1422: if not self._v_downloadBasket.get(threadName,None):
1423: for thread in threading.enumerate():
1424: if threadName == thread.getName():
1425: self._v_downloadBasket[threadName]=thread
1426:
1427: if self._v_downloadBasket.get(threadName,None) and (self._v_downloadBasket[threadName] is not None) and (not self._v_downloadBasket[threadName].end) :
1428:
1429: wait_template=self.aq_parent.ZopeFind(self.aq_parent,obj_ids=['wait_template'])
1430: if wait_template:
1431: return wait_template[0][1]()
1432:
1433: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','downloadBasketWait.zpt')).__of__(self)
1434: return pt(txt=self.absolute_url()+'/downloadObjectsAsOneFileFinally',threadName=threadName,
1435: counter=self._v_downloadBasket[threadName].getCounter(),
1436: number=self._v_downloadBasket[threadName].getNumberOfFiles())
1437: else:
1438:
1439:
1440: logging.debug("FINISHED")
1441: if not self._v_downloadBasket.get(threadName,None):
1442: for thread in threading.enumerate():
1443: if threadName == thread.getName():
1444: self._v_downloadBasket[threadName]=thread
1445:
1446: #files = self._v_downloadBasket[threadName].result
1447: # lade die files und die locked files, bei grossen Baskets muss u.U. gewartet werden
1448: # bis das Commit aus dem Thread alles geschrieben hat, in dem Falle existiert resultHash[threadName]
1449: # noch nicht.
1450: o1 = file("/tmp/"+threadName,'r')
1451: files=pickle.load(o1)
1452: os.remove("/tmp/"+threadName)
1453: o2 = file("/tmp/"+threadName+'_lockedFiles','r')
1454:
1455: lockedFiles=pickle.load(o2)
1456: os.remove("/tmp/"+threadName+'_lockedFiles')
1457: # try:
1458: # files=self.basketContainer.resultHash[threadName]
1459: # except:
1460: # i=0
1461: # while (not self.basketContainer.resultHash.has_key(threadName)) and (i<100):
1462: # logging.debug(" downloadFinally: I am waiting for thread %s to write the resultHashfile: %s"%(threadName,i))
1463: # time.sleep(5)
1464: # i+=1
1465: # files=self.basketContainer.resultHash[threadName]
1466: #
1467: # try:
1468: # lockedFiles=self.basketContainer.resultLockedHash[threadName]
1469: # except:
1470: # i=0
1471: # while (not self.basketContainer.resultLockedHash.has_key(threadName)) and (i<100):
1472: # logging.debug(" downloadFinally: I am waiting for thread %s to write the LockedHashfile: %s"%(threadName,i))
1473: # time.sleep(5)
1474: # i+=1
1475: # lockedFiles=self.basketContainer.resultLockedHash[threadName]
1476:
1477: # fh=file("/var/tmp/test")
1478: #ret =fh.read()
1479:
1480: if (not isinstance(self.aq_parent,CDLIBasket)):
1481: basket_name=self.aq_parent.aq_parent.title+"_V"+self.getId()
1482: else:
1483: basket_name=self.aq_parent.title+"_V"+self.getId()
1484:
1485:
1486:
1487: #write basketname to header of atf file
1488:
1489:
1490: self.REQUEST.RESPONSE.setHeader("Content-Disposition","""attachement; filename="%s.atf" """%basket_name)
1491: self.REQUEST.RESPONSE.setHeader("Content-Type","application/octet-stream")
1492: #length=len(ret)
1493: #self.REQUEST.RESPONSE.setHeader("Content-Length",length)
1494:
1495: ret="#basket: %s\n"%basket_name
1496: self.REQUEST.RESPONSE.write(ret)
1497:
1498: for fileName in files:
1499: logging.debug("download: %s"%fileName)
1500: try:
1501: self.REQUEST.RESPONSE.write(file(fileName).read())
1502: except:
1503: logging.error("downloadasonefile: cannot read %s"%fileName)
1504:
1505:
1506: self.REQUEST.RESPONSE.write("\n# locked files\n")
1507: for fileName in lockedFiles:
1508: self.REQUEST.RESPONSE.write("# %s by %s\n"%fileName)
1509:
1510: self.REQUEST.RESPONSE.write("# locked files end\n")
1511:
1512: #del self.basketContainer.resultHash[threadName]
1513: #del self.basketContainer.resultLockedHash[threadName]
1514:
1515: def numberOfItems(self):
1516: """return anzahl der elemente im basket"""
1517: return self.content.numberOfItems()
1518:
1519: def getTime(self):
1520: """getTime"""
1521: #return self.bobobase_modification_time().ISO()
1522:
1523: if hasattr(self,'time'):
1524: return time.strftime("%Y-%m-%d %H:%M:%S",self.time)
1525: elif hasattr(self,'timefixed'):
1526: return self.timefixed
1527: else:
1528: setattr(self,'timefixed',self.bobobase_modification_time().ISO())
1529: return self.bobobase_modification_time().ISO()
1530:
1531: def getContent(self):
1532: """get Basket Content"""
1533: logging.debug("retrieving content A")
1534: cnt = self.content
1535: logging.debug("retrieving content: obj %s"%cnt)
1536: tmp = self.content.getContent()
1537: logging.debug("got content")
1538: return tmp
1539:
1540:
1541: def __init__(self,id,user,comment="",basketContent=[]):
1542: """ init a basket version"""
1543: self.id=id
1544: self.comment=comment
1545: self._setObject('content',BasketContent(basketContent))
1546: #self.basketContent=basketContent[0:]a
1547: self.user=user
1548: self.time=time.localtime()
1549:
1550: def getUser(self):
1551: """get user"""
1552: return self.user
1553:
1554: def getComment(self):
1555: """get Comment"""
1556: return self.comment
1557:
1558: security.declareProtected('manage','index_html')
1559: def index_html(self):
1560: """view the basket"""
1561: logging.debug("start index_html - Basket version")
1562: if self.REQUEST.get('change',False):
1563: ob=self.aq_parent.updateObjects(self.REQUEST['change'])
1564:
1565: self.REQUEST.RESPONSE.redirect(ob.absolute_url())#go to new basket, because changing generates a new basket
1566: logging.debug("start index_html - Basket version:template")
1567: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','BasketVersionMain.zpt')).__of__(self)
1568: return pt()
1569:
1570: def getObjUrl(self,result):
1571: """getUrl of the version of the object"""
1572:
1573: founds=self.CDLICatalog.search({'title':result})
1574: if len(founds)>0:
1575: return founds[0].getObject().getLastVersion().absolute_url()
1576:
1577: else: #assume version number
1578: splitted=result.split("_")
1579: founds=self.CDLICatalog.search({'title':splitted[1]})
1580: return founds[0].getObject().getLastVersion().absolute_url()+'/'+result
1581:
1582: def manage_addCDLIBasketVersion(self,user,comment="",basketContent=[],RESPONSE=None):
1583: """add a version"""
1584:
1585: #check for already existing versions
1586:
1587: lastVersion=self.getLastVersion()
1588: if lastVersion is None:
1589: newId=str(1)
1590: else:
1591: newId=str(int(lastVersion.getId())+1)
1592:
1593: ob=CDLIBasketVersion(newId,user,comment,basketContent)
1594:
1595: self._setObject(newId, ob)
1596:
1597: if RESPONSE is not None:
1598: RESPONSE.redirect('manage_main')
1599: else:
1600: return ob
1601:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>