From 9ad4cbb5d245d9cfa2b56bd08267f9d9f63a9313 Mon Sep 17 00:00:00 2001 From: Jan Vonka Date: Mon, 18 Mar 2013 09:23:29 +0000 Subject: [PATCH] =?UTF-8?q?Merged=20BRANCHES/DEV/CONV=5FHEAD=20to=20HEAD:?= =?UTF-8?q?=20=20=20=2047880:=20Create=20branch=20for=20Cloud=20Convergenc?= =?UTF-8?q?e=20from=20the=20latest=20state=20of=20HEAD=20(Revision=2047874?= =?UTF-8?q?)=20=20=20=2047886:=20Merged=20BRANCHES/DEV/CONV=5FV413=20to=20?= =?UTF-8?q?BRANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2033052:=20(R?= =?UTF-8?q?ECORD=20ONLY)=20Branch=20for=20Enterprise=204.0=20service=20pac?= =?UTF-8?q?k=20development=20=20=20=20=20=20=20=20=2038002:=20(RECORD=20ON?= =?UTF-8?q?LY)=20Create=20branch=20for=204.1=20Enterprise=20releases,=20ba?= =?UTF-8?q?sed=20on=204.0.2=20=20=20=20=20=20=20=20=2038003:=20(RECORD=20O?= =?UTF-8?q?NLY)=20Update=20version=20to=204.1.0=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?38079:=20(RECORD=20ONLY)=20Updated=20schema=20version=20to=2051?= =?UTF-8?q?00=20=20=20=20=20=20=20=20=2038536:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20V4.1-BUG-FIX=20to=20V4.1=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2038219:=20ALF-14674:=20DOS=20voodoo=20to=20make=20start=5F?= =?UTF-8?q?deployment.bat=20work,=20as=20installed=20by=20Bitrock=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2038344:=20ALF-14674:=20Deployme?= =?UTF-8?q?nt=20installer=20still=20doesn't=20work=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20-=20Use=20${installdir.escape=5Fbackslashes}?= =?UTF-8?q?=20instead=20of=20${installdir}=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2038471:=20ALF-14674:=20Deployment=20installer=20stil?= =?UTF-8?q?l=20doesn't=20work=20=20=20=20=20=20=20=20=20=20=20=20=20=20-?= =?UTF-8?q?=20Correction=20to=20use=20of=20${installdir.escape=5Fbackslash?= =?UTF-8?q?es}=20=20=20=20=20=20=20=20=2039519:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20PATCHES/V4.0.2=20to=20V4.1=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2038899:=20ALF-15005:=20Merged=20V4.0-BUG-FIX=20to=20PAT?= =?UTF-8?q?CHES/V4.0.2=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=203?= =?UTF-8?q?7920:=20ALF-13816:=20Permission=20Denied=20on=20web-client=20br?= =?UTF-8?q?owsing=20if=20parent=20does=20not=20inherit=20permissions=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20-=20FileF?= =?UTF-8?q?olderService=20getNamePath()=20now=20performs=20toFileInfo()=20?= =?UTF-8?q?as=20SystemUser.=20=20=20=20=20=20=20=20=20=20=20=20=20=2038900?= =?UTF-8?q?:=20ALF-15005:=20Merged=20V4.1-BUG-FIX=20to=20PATCHES/V4.0.2=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2038549:=20ALF-11?= =?UTF-8?q?861:=20Maintain=20the=20same=20defuault=20root=20of=20WebDav=20?= =?UTF-8?q?for=20Alfresco=204.0=20as=20was=20in=20pre-4.0=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20Removed=20overridi?= =?UTF-8?q?ng=20protocols.rootPath=20property=20from=20installer=20and=20e?= =?UTF-8?q?nterprise=20overlay=20versions=20of=20alfresco-global.propertie?= =?UTF-8?q?s=20so=20that=20correct=20setting=20in=20repository.properties?= =?UTF-8?q?=20is=20used.=20=20=20=20=20=20=20=20=20=20=20=20=20=2039494:?= =?UTF-8?q?=20ALF-15213=20/=20ALF-15170:=20Can't=20change=20folder=20permi?= =?UTF-8?q?ssions=20in=20Private=20or=20Public-moderated=20sites=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20-=20Fix=20by=20Dmitry?= =?UTF-8?q?=20V=20=20=20=20=20=20=20=20=2044843:=20(RECORD=20ONLY)=20Creat?= =?UTF-8?q?ed=20hotfix=20branch=20off=20V4.1=20build=20372=20revision=2044?= =?UTF-8?q?743=20(candidate=204.1.2=20release)=20=20=20=20=20=20=20=20=204?= =?UTF-8?q?5708:=20(RECORD=20ONLY)=20Merged=20PATCHES/V4.1.2=20to=20PATCHE?= =?UTF-8?q?S/V4.1.3=20=20=20=20=20=20=20=20=20=20=20=20=20=2045570:=20Merg?= =?UTF-8?q?ed=20V3.4-BUG-FIX=20to=20PATCHES/V4.1.2=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2043939:=20ALF-17197=20/=20ALF-16917:?= =?UTF-8?q?=20Merged=20PATCHES/V3.4.11=20to=20V3.4-BUG-FIX=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2043896:=20MNT-198:?= =?UTF-8?q?=20Activity=20feeds=20get=20not=20generated=20in=20private=20si?= =?UTF-8?q?tes=20for=20added=20files=20if=20username=20in=20LDAP-AD=20cont?= =?UTF-8?q?ains=20uppercase=20letters=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20-=20Now=20we=20can=20cope=20with=20a=20?= =?UTF-8?q?runAs=20where=20the=20username=20is=20in=20the=20wrong=20case?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2045714:=20(RECORD=20ONLY)=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/V4.1-BUG-FIX=20to=20PATCHES/DEV/V4.1.3=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2045513:=20MNT-279:=20Use=20bina?= =?UTF-8?q?ry=20search=20in=20cached=20authority=20search=20to=20cut=20dow?= =?UTF-8?q?n=20search=20time=20when=20a=20group=20contains=20an=20astronom?= =?UTF-8?q?ical=20number=20of=20authorities=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20-=20Experimental=20fix=20to=20cut=20down=20on=20?= =?UTF-8?q?severe=20profiling=20hit=20=20=20=20=20=20=20=20=2045715:=20(RE?= =?UTF-8?q?CORD=20ONLY)=20Merged=20BRANCHES/DEV/V4.1-BUG-FIX=20to=20PATCHE?= =?UTF-8?q?S/V4.1.3=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2044848:=20F?= =?UTF-8?q?ix=20for=20=20=20=20=20ALF-17178=20SolrLuceneAnalyser.findAnaly?= =?UTF-8?q?ser=20generating=20InavlidQNameExceptions=20wher=20they=20are?= =?UTF-8?q?=20easily=20protected.=20=20=20=20=20=20=20=20=2046188:=20(RECO?= =?UTF-8?q?RD=20ONLY)=20Merged=20BRANCHES/DEV/V4.1-BUG-FIX=20to=20PATCHES/?= =?UTF-8?q?V4.1.3=20=20=20=20=20=20=20=20=20=20=20=20=20=2046014:=20Fix=20?= =?UTF-8?q?for=20ALF-17732=20-=20SWF=20files=20are=20considered=20insecure?= =?UTF-8?q?=20content=20and=20should=20not=20be=20displayed=20directly=20i?= =?UTF-8?q?n=20the=20browser.=20=20=20=20=20=20=20=20=20=20=20=20=20=20461?= =?UTF-8?q?60:=20Fix=20for=20ALF-17759=20-=20HTML=20files=20are=20stripped?= =?UTF-8?q?=20from=20metadata=20and=20style=20information=20after=20they?= =?UTF-8?q?=20are=20uploaded.=20=20=20=20=20=20=20=20=20=20=20=20=20=20461?= =?UTF-8?q?65:=20Fix=20for=20ALF-17787=20-=20Site=20Members=20'All=20Membe?= =?UTF-8?q?rs'=20link=20should=20not=20run=20query=20immediately=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2046169:=20Fix=20for=20ALF-17787?= =?UTF-8?q?=20-=20Site=20Members=20'All=20Members'=20link=20should=20not?= =?UTF-8?q?=20run=20query=20immediately=20-=20missing=20file=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2046186:=20Fix=20for=20ALF-17786=20?= =?UTF-8?q?-=20Site=20dashboard=20page=20issues=20too=20many=20requests=20?= =?UTF-8?q?(Site=20Members=20dashlet=20issues=20avatar=20requests=20when?= =?UTF-8?q?=20it=20doesn't=20need=20too)=20=20=20=20=20=20=20=20=2046242:?= =?UTF-8?q?=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/V4.1-BUG-FIX=20to=20?= =?UTF-8?q?PATCHES/V4.1.3:=20=20=20=20=20=20=20=20=20=20=20=20=20=2046184:?= =?UTF-8?q?=20Refactoring=20a=20test=20class=20to=20use=20JUnit=20Rules=20?= =?UTF-8?q?-=20as=20part=20of=20attempt=20to=20reproduce=20ALF-17797.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2046192:=20Enhancement=20t?= =?UTF-8?q?o=20JUnit=20Rule=20TemporaryNodes.java=20as=20required=20by=20f?= =?UTF-8?q?ix=20for=20ALF-17797.=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?46194:=20Fix=20for=20ALF-17797.=20AddFailedThumbnailActionExecu?= =?UTF-8?q?ter=20is=20failing.=20=20=20=20=20=20=20=20=2046710:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Create=20branch=20for=20Cloud=20Convergence=20from?= =?UTF-8?q?=20the=20latest=20state=20of=204.1.3=20(RC5,=20Build=2085,=20Re?= =?UTF-8?q?vision=2046648)=20=20=20=2047908:=20Merged=20from=20DEV/CONV=5F?= =?UTF-8?q?V143=20to=20DEV/CONV=5FHEAD=20=20=20=20=20=20=20=20=2046788:=20?= =?UTF-8?q?Merged=20from=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5F?= =?UTF-8?q?V413=20=20=20=20=20=20=20=20=20=20=20=20Merged=20BRANCHES/DEV/T?= =?UTF-8?q?HOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030323:=20(RECORD=20ONLY)=20Merged=20HEAD=20to=20?= =?UTF-8?q?BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030171:=20ALF-9613:=20caching=20content=20store.=20V?= =?UTF-8?q?arious=20improvements=20and=20bug=20fixes.=20Including:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030325:=20THOR-114:=20S3?= =?UTF-8?q?=20content=20store=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?30326:=20THOR-128:=20S3=20content=20store=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030333:=20THOR-139=20F101:=20Get=20accou?= =?UTF-8?q?nt=20for=20user=20e-mail=20id=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030335:=20Merge=20from=20THOR0=20to=20THOR1=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20r30274:=20THOR-135?= =?UTF-8?q?=20is=20email=20address=20accepted=20by=20Alfresco=3F=20Part=20?= =?UTF-8?q?One.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030340:=20THOR-?= =?UTF-8?q?99:=20Thor=20module=20-=20enable=20tests=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030341:=20Removing=20duplicate=20account?= =?UTF-8?q?-service-context.xml=20file.=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030343:=20Merge=20THOR0=20to=20THOR1=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030339:=20Test=20email=20?= =?UTF-8?q?singup=20in=20Share=20complete=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2030338:=20New=20form=20runtime=20f?= =?UTF-8?q?eatures:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20-=20Yellow=20background=20is=20displayed=20fo?= =?UTF-8?q?r=20mandatory=20fields=20without=20value=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20-=20Red=20ba?= =?UTF-8?q?ckground=20dis=20displayed=20for=20fields=20with=20validation?= =?UTF-8?q?=20errors=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20-=20Error=20message=20is=20displayed=20in=20a?= =?UTF-8?q?=20balloon=20when=20fields=20with=20error=20has=20focus=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20-=20Using=20balloons=20is=20now=20the=20default=20method=20o?= =?UTF-8?q?f=20displaying=20errors=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20-=20Removed=20balloon=20code?= =?UTF-8?q?=20form=20create=20site=20menu=20since=20its=20now=20handled=20?= =?UTF-8?q?automatically=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20-=20An=20alternative=20to=20balloons=20?= =?UTF-8?q?are=20"error=20containers"=20(div=20with=20clickable=20red=20te?= =?UTF-8?q?xt=20labels=20focusing=20the=20field):=20setErrorContainer(divE?= =?UTF-8?q?l)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20-=20Its=20possible=20to=20setMultipleErrors(true)?= =?UTF-8?q?=20to=20display=20all=20the=20forms/fields=20errors=20in=20the?= =?UTF-8?q?=20"error=20container"/ballon.=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20-=20Its=20possible=20to?= =?UTF-8?q?=20turn=20of=20the=20balloons=20and=20error=20containers=20comp?= =?UTF-8?q?lete=20by=20setting=20setErrorContainer(null)=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20-=20js=20?= =?UTF-8?q?validation=20handlers=20no=20longer=20needs=20to=20handle=20the?= =?UTF-8?q?=20messages=20OR=20the=20css=20classes=20for=20mandatory=20&=20?= =?UTF-8?q?invalid=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030344:=20Mi?= =?UTF-8?q?ssing=20value=20check=20caused=20js=20undefined=20error=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030346:=20Minor=20css=20f?= =?UTF-8?q?orm=20fixes=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030347:?= =?UTF-8?q?=20THOR-126:=20S3=20content=20store=20-=20do=20not=20swallow=20?= =?UTF-8?q?exceptions=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030348:?= =?UTF-8?q?=20THOR-66:=20disable=20unused=20services/features=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2030349:=20THOR-137=20F88:=20Add?= =?UTF-8?q?=20existing=20external=20user=20(from=20another=20network)=20ch?= =?UTF-8?q?eckpoint=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030350:=20T?= =?UTF-8?q?HOR-135=20Is=20email=20address=20accepted=20by=20Alfresco.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2046789:=20Merged=20from=20BRANCHES/DEV/C?= =?UTF-8?q?LOUD2=20to=20BRANCHES/DEV/CONV=5FV413=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2035594:=20Fix=20merge=20issue=20=20=20=2047930:=20Me?= =?UTF-8?q?rged=20BRANCHES/DEV/CONV=5FV413=20to=20BRANCHES/DEV/CONV=5FHEAD?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=2046762:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2046768:=20(RECORD=20ONLY)=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2046769:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CL?= =?UTF-8?q?OUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2046778:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046780:?= =?UTF-8?q?=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCH?= =?UTF-8?q?ES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046786:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CON?= =?UTF-8?q?V=5FV413:=20=20=20=20=20=20=20=20=2046791:=20(RECORD=20ONLY)=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2046792:=20(RECORD=20ONLY)=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2046808:=20(RECORD=20ONLY)=20Merged=20BRANCHES/?= =?UTF-8?q?DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2046809:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD?= =?UTF-8?q?2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046?= =?UTF-8?q?819:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BR?= =?UTF-8?q?ANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046829:=20(REC?= =?UTF-8?q?ORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/?= =?UTF-8?q?CONV=5FV413:=20=20=20=20=20=20=20=20=2046839:=20(RECORD=20ONLY)?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=2046842:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2046844:=20(RECORD=20ONLY)=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2046846:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CL?= =?UTF-8?q?OUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2046847:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046876:?= =?UTF-8?q?=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCH?= =?UTF-8?q?ES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046877:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CON?= =?UTF-8?q?V=5FV413:=20=20=20=20=20=20=20=20=2046878:=20(RECORD=20ONLY)=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2046879:=20(RECORD=20ONLY)=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2046880:=20(RECORD=20ONLY)=20Merged=20BRANCHES/?= =?UTF-8?q?DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2046881:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD?= =?UTF-8?q?2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=2047947:=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FV413=20to=20BRANCHES/DEV/CONV=5FHEAD:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2046737:=20Merged=20BRANCHES/DEV/CLOUD2?= =?UTF-8?q?=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2035288:=20Alfresco=20Cloud=20(from=20BRANCHES/V4.0)?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2035389:=20Merged=20BRA?= =?UTF-8?q?NCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030170:=20Thor=20branch?= =?UTF-8?q?=20based=20on=20Swift=20feature=20complete=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030185:=20Merged=20BRANCHES/?= =?UTF-8?q?DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2028973:=20THOR-1:?= =?UTF-8?q?=20verify=20ability=20to=20create=20DB=20schema=20programatical?= =?UTF-8?q?ly=20on=20AWS=20RDS=20(for=20MySQL=20&=20Oracle)=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2028999:?= =?UTF-8?q?=20THOR-3:=20Tenant=20Routing=20Data=20Source=20(dynamic=20tena?= =?UTF-8?q?nt-aware=20DB=20connection=20pools)=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029022:=20THOR-1:?= =?UTF-8?q?=20verify=20ability=20to=20create=20DB=20schema=20programatical?= =?UTF-8?q?ly=20on=20AWS=20RDS=20(for=20MySQL=20&=20Oracle)=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029031:?= =?UTF-8?q?=20THOR-1:=20verify=20ability=20to=20create=20DB=20schema=20pro?= =?UTF-8?q?gramatically=20on=20AWS=20RDS=20(for=20MySQL=20&=20Oracle)=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030186:=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20(3=20c?= =?UTF-8?q?onflicts=20resolved)=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2029116:=20THOR-3:=20Tenant=20Routi?= =?UTF-8?q?ng=20Data=20Source=20(dynamic=20tenant-aware=20DB=20connection?= =?UTF-8?q?=20pools)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029174:=20THOR-24=20Set=20up=20new=20Alfresco?= =?UTF-8?q?=20AMP=20module=20project.=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2029186:=20THOR-25=20Copy=20a?= =?UTF-8?q?nd=20refactor=20Account=20Service=20from=20SambaJAM=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20291?= =?UTF-8?q?93:=20ImporterComponent=20-=20prep=20for=20THOR-7=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20291?= =?UTF-8?q?98:=20THOR-7:=20=20Tenant=20Service=20API=20-=20Create=20Tenant?= =?UTF-8?q?=20(using=20separate=20DB=20schema)=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029204:=20THOR-29?= =?UTF-8?q?=20Account=20Type=20Registry=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2029234:=20THOR-7:=20=20Te?= =?UTF-8?q?nant=20Service=20API=20-=20Create=20Tenant=20(using=20separate?= =?UTF-8?q?=20DB=20schema)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2029246:=20THOR-7:=20=20Tenant=20Service?= =?UTF-8?q?=20API=20-=20Create=20Tenant=20(using=20separate=20DB=20schema)?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2029251:=20THOR-30=20Added=20AccountDAO=20interface=20al?= =?UTF-8?q?ong=20with=20two=20implementations:=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20Accoun?= =?UTF-8?q?tDAOImpl=20(not=20implemented)=20which=20will=20manage=20Accoun?= =?UTF-8?q?t=20data=20in=20an=20RDB=20via=20iBatis.=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?AccountDAO=5FInMemory=20which=20manages=20AccountInfo=20in=20si?= =?UTF-8?q?mple=20HashMaps=20for=20testing=20purposes=20only.=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20292?= =?UTF-8?q?58:=20THOR-28=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2029259:=20Addendum=20to=20THOR-25.=20Mov?= =?UTF-8?q?ed=20account-service=20spring=20config=20into=20a=20subfolder.?= =?UTF-8?q?=20(trivial)=20=20=20=20=20=20=20=20=20=20=20=20=20=2035393:=20?= =?UTF-8?q?(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/D?= =?UTF-8?q?EV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20-=20fix=20up=20classpath=20(remove=20mybatis=201.0.0?= =?UTF-8?q?=20->=201.0.1=20and=20chemistry=200.4.0=20->=200.6.0)=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2035411:=20(RECORD=20ONLY)=20Mer?= =?UTF-8?q?ged=20BRANCHES/DEV/V4.0-BUG-FIX=20to=20BRANCHES/DEV/CLOUD1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2035409:=20?= =?UTF-8?q?Merged=20HEAD=20to=20BRANCHES/DEV/V4.0-BUG-FIX:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2035399:?= =?UTF-8?q?=20ALF-12874:=20Schema=20reference=20files=20are=20out=20of=20d?= =?UTF-8?q?ate.=20=20=20=20=20=20=20=20=20=20=20=20=20=2035452:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Merged=20BRANCHES/DEV/V4.0-BUG-FIX=20to=20BRANCHES/D?= =?UTF-8?q?EV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2034219:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/D?= =?UTF-8?q?EV/V4.0-BUG-FIX:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2032096:=20THOR-429:=20Fix=20"MT:=20Th?= =?UTF-8?q?umbnail=20+=20Preview=20are=20not=20updated=20(after=20uploadin?= =?UTF-8?q?g=20new=20version)"=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2032125:=20THOR-429:=20Fix=20"MT:?= =?UTF-8?q?=20Thumbnail=20+=20Preview=20are=20not=20updated=20(after=20upl?= =?UTF-8?q?oading=20new=20version)"=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2034220:=20Minor:=20follow-on=20to=20r34219?= =?UTF-8?q?=20(ALF-11563)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2034747:=20ALF-13262:=20adding=20missing=20indexes=20?= =?UTF-8?q?for=20new=20schema's=20(activiti-schema=20create)=20+=20schema?= =?UTF-8?q?=20patch=20for=20existing=20schema=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2035417:=20Merged=20BRANCHES/DEV?= =?UTF-8?q?/THOR0=20to=20BRANCHES/DEV/V4.0-BUG-FIX:=20(THOR-6=20/=20ALF-13?= =?UTF-8?q?755)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2029356:=20THOR-6:=20MT=20is=20configured=20(but?= =?UTF-8?q?=20not=20enabled)=20by=20default=20-=20will=20be=20auto-enabled?= =?UTF-8?q?=20when=20first=20tenant=20is=20created=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029455:=20THOR-6?= =?UTF-8?q?:=20build=20test/fix=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2029471:=20THOR-6:=20build=20test/f?= =?UTF-8?q?ix=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=203?= =?UTF-8?q?5423:=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/V4.0-BU?= =?UTF-8?q?G-FIX:=20(THOR-4=20/=20ALF-13756)=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2029500:=20THOR-4:=20Re?= =?UTF-8?q?place=20Tenant=20attributes=20with=20Tenant=20table=20(alf=5Fte?= =?UTF-8?q?nant)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2029501:=20THOR-4:=20Replace=20Tenant=20attributes?= =?UTF-8?q?=20with=20Tenant=20table=20(alf=5Ftenant)=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029503:=20THO?= =?UTF-8?q?R-4:=20Replace=20Tenant=20attributes=20with=20Tenant=20table=20?= =?UTF-8?q?(alf=5Ftenant)=20=20=20=2047949:=20Merged=20HEAD=20to=20BRANCHE?= =?UTF-8?q?S/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2047914:=20Merge=20f?= =?UTF-8?q?ix=20for=20org.alfresco.repo.cache.AbstractAsynchronouslyRefres?= =?UTF-8?q?hedCache=20R=2046078,=2046079,=2046121=20=20=20=2047958:=20M?= =?UTF-8?q?erged=20BRANCHES/DEV/CONV=5FV413=20to=20BRANCHES/DEV/CONV=5FHEA?= =?UTF-8?q?D:=20=20=20=20=20=20=20=20=2046746:=20Merged=20BRANCHES/DEV/CLO?= =?UTF-8?q?UD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2035455:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRAN?= =?UTF-8?q?CHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030187:=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHE?= =?UTF-8?q?S/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2029260:=20THOR:=20Initial=20Tenant=20Admin?= =?UTF-8?q?=20Service=20REST=20API=20-=20create,=20delete,=20get=20(list)?= =?UTF-8?q?=20web=20scripts=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2029356:=20THOR-6:=20MT=20is=20configu?= =?UTF-8?q?red=20by=20default=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2029366:=20THOR-59:=20selectively=20di?= =?UTF-8?q?sable=20certain=20test=20suites=20(for=20THOR=20dev=20build=20p?= =?UTF-8?q?lan)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2029377:=20THOR-59:=20selectively=20disable=20cert?= =?UTF-8?q?ain=20test=20suites=20(for=20THOR=20dev=20build=20plan)=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2029398:=20Refactoring=20of=20code=20to=20remove=20deprecation?= =?UTF-8?q?=20warnings.=20Replaced=20lots=20of=20object.field=20accesses?= =?UTF-8?q?=20with=20object.getField()=20calls.Trivial=20changes,=20but=20?= =?UTF-8?q?with=20so=20many=20warnings=20I=20can't=20see=20the=20wood=20fo?= =?UTF-8?q?r=20the=20trees.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2029400:=20THOR-59:=20selectively=20di?= =?UTF-8?q?sable=20certain=20test=20suites=20(for=20THOR=20dev=20build=20p?= =?UTF-8?q?lan)=20=20=20=20=20=20=20=20=20=20=20=20=20=2035456:=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030188:=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029442:=20?= =?UTF-8?q?THOR-59:=20selectively=20disable=20certain=20test=20suites=20(f?= =?UTF-8?q?or=20THOR=20dev=20build=20plan)=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2029453:=20THOR-59:=20s?= =?UTF-8?q?electively=20disable=20certain=20test=20suites=20(for=20THOR=20?= =?UTF-8?q?dev=20build=20plan)=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2029455:=20THOR-76:=20track=20THOR?= =?UTF-8?q?=20build=20test=20failures=20and=20fix-up=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029471:=20THO?= =?UTF-8?q?R-76:=20track=20THOR=20build=20test=20failures=20and=20fix-up?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2035459:=20Merged=20BRA?= =?UTF-8?q?NCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030189:=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029473:=20Prelim?= =?UTF-8?q?inary=20checkin=20for=20THOR-44.=20Created=20placeholder=20inte?= =?UTF-8?q?rface/impl/spring=20config=20for=20a=20new=20UserService.=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2029497:=20THOR-76:=20track=20THOR=20build=20test=20failures?= =?UTF-8?q?=20and=20fix-up=20(=20LicenseComponentTest)=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029500:=20?= =?UTF-8?q?THOR-4:=20Replace=20Tenant=20attributes=20with=20Tenant=20table?= =?UTF-8?q?=20(alf=5Ftenant)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2029501:=20THOR-4:=20Replace=20Tenant?= =?UTF-8?q?=20attributes=20with=20Tenant=20table=20(alf=5Ftenant)=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?29503:=20THOR-4:=20Replace=20Tenant=20attributes=20with=20Tenan?= =?UTF-8?q?t=20table=20(alf=5Ftenant)=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2029511:=20THOR-59:=20selecti?= =?UTF-8?q?vely=20disable=20certain=20test=20suites=20(for=20THOR=20dev=20?= =?UTF-8?q?build=20plan)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2029512:=20Adding=20a=20new=20JUnit4=20te?= =?UTF-8?q?st=20class=20with=20an=20@Ignore'd=20test=20in=20it=20-=20to=20?= =?UTF-8?q?see=20how=20Bamboo=20reports=20these.=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029514:=20THOR:?= =?UTF-8?q?=20Initial=20Tenant=20Admin=20Service=20REST=20API=20-=20create?= =?UTF-8?q?,=20delete,=20list=20web=20scripts=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029515:=20THOR-59:?= =?UTF-8?q?=20selectively=20disable=20certain=20test=20suites=20(for=20THO?= =?UTF-8?q?R=20dev=20build=20plan)=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2029521:=20THOR-79=20-=20mark=20?= =?UTF-8?q?AVM=20sitestore=20as=20unindexed=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2035461:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHE?= =?UTF-8?q?S/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030190:=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/D?= =?UTF-8?q?EV/THOR1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029533:=20THOR-59:=20exclude=20certain=20N/A?= =?UTF-8?q?=20tests=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029555:=20THOR-76:=20track=20THOR=20build=20te?= =?UTF-8?q?st=20failures=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2029630:=20Added=20ant=20build=20targets?= =?UTF-8?q?=20for=20Cloud=20Module=20and=20a=20new=20executable=20for=20th?= =?UTF-8?q?e=20Alfresco=20devenv.=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2029664:=20THOR-76:=20exclude=20?= =?UTF-8?q?system=20test=20suites=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2029667:=20THOR-64:=20add=20init?= =?UTF-8?q?ial=20support=20for=20tenant=20routing=20data=20source=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?29676:=20THOR-76:=20exclude=20intermittent=20ActionTrackingServ?= =?UTF-8?q?iceImplTest=20(pending=20ALF-9773=20&=20ALF-9774)=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20296?= =?UTF-8?q?77:=20THOR-80:=20MT-aware=20S3=20content=20store=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029678:?= =?UTF-8?q?=20THOR-80:=20MT-aware=20S3=20content=20store=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029680:=20?= =?UTF-8?q?THOR-80:=20MT-aware=20S3=20content=20store=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029693:=20THO?= =?UTF-8?q?R-80:=20MT-aware=20S3=20content=20store=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029694:=20THOR-8?= =?UTF-8?q?0:=20MT-aware=20S3=20content=20store=20=20=20=2047959:=20CONV?= =?UTF-8?q?=5FHEAD:=20CLOUD-1348=20-=20comment=20back=20in=20MultiTDemoTes?= =?UTF-8?q?t.testDeleteAllTenants=20=20=20=2047967:=20Merged=20BRANCHES/DE?= =?UTF-8?q?V/CONV=5FV413=20to=20BRANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2046748:=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCH?= =?UTF-8?q?ES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20=20=20=20=20=2035?= =?UTF-8?q?464:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030195:?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2029774:=20Refactor=20Account=20DAO=20and=20Service.=20Boost?= =?UTF-8?q?=20Tests.=20Add=20appropriate=20headers.=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029776:=20THO?= =?UTF-8?q?R-76:=20exclude=20intermittent=20ActionTrackingServiceImplTest?= =?UTF-8?q?=20(pending=20ALF-9773=20&=20ALF-9774)=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029795:=20Implem?= =?UTF-8?q?ented=20MyBatis-backed=20Account=20DAO:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029817:=20Move?= =?UTF-8?q?=20(and=20rename)=20user=20service=20from=20repository=20to=20t?= =?UTF-8?q?hor=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20301?= =?UTF-8?q?96:=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2029827:=20THOR-69:=20TenantAdminDAO=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029832:=20THO?= =?UTF-8?q?R-78:=20fix=20tenantEntityCache=20(shared)=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029834:=20THO?= =?UTF-8?q?R-111:=20experimental=20config=20option=20for=20S3=20content=20?= =?UTF-8?q?store=20to=20support=20flat=20root=20(ie.=20all=20tenant=20file?= =?UTF-8?q?s=20in=20single=20folder)=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2029856:=20THOR=20updates=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2029857:=20THOR-76:=20exclude=20build=20components/projects?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2046761:=20Merged=20BRANCHES/DEV/CLOUD?= =?UTF-8?q?2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2035478:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRAN?= =?UTF-8?q?CHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030198:=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHE?= =?UTF-8?q?S/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2029869:=20THOR-92.=20BPMN2.0=20workflow=20d?= =?UTF-8?q?efinition=20for=20account=20self-signup.=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029871:=20THO?= =?UTF-8?q?R-93.=20REST=20API=20for=20self=20signup=20(and=20miscellaneous?= =?UTF-8?q?=20related=20items).=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2029882:=20THOR-102:=20Faster=20Cre?= =?UTF-8?q?ateTenant=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029888:=20THOR-95.=20Placeholder=20email=20tem?= =?UTF-8?q?plate=20for=20self-signup.=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2029889:=20Completion=20of=20?= =?UTF-8?q?THOR-95.=20Placeholder=20emails=20for=20self-signup.=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20Added=20a=20'you've=20already=20registered'=20te?= =?UTF-8?q?mplate.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029896:=20THOR-89F100:=20Create=20User=20Found?= =?UTF-8?q?ation=20API=E2=80=A6=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2029912:=20Fix=20issue=20where=20mo?= =?UTF-8?q?dule=20believed=20it=20was=20still=20executed=20after=20delete?= =?UTF-8?q?=20tenant=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029940:=20THOR-96.=20First=20cut=20of=20a=20si?= =?UTF-8?q?gnup=20email=20sender=20delegate.=20This=20will=20be=20refined?= =?UTF-8?q?=20later=20-=20probably=20both=20in=20this=20sprint=20and=20the?= =?UTF-8?q?=20next.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029966:=20Fixing=20InvitationServiceImplTest?= =?UTF-8?q?=20failing=20tests,=20which=20are=20failing=20because=20the=20e?= =?UTF-8?q?mail=20templates=20are=20not=20there.=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029978:=20THOR-8?= =?UTF-8?q?9:=20Switch=20tenant=20for=20person=20creation=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029982:?= =?UTF-8?q?=20THOR-89:=20Fix=20multi-domain=20account=20creation=20test=20?= =?UTF-8?q?after=20review=20with=20Jan=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2029983:=20THOR-102:=20Faster?= =?UTF-8?q?=20CreateTenant=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2029985:=20THOR-90:=20F99=20Is=20email=20?= =?UTF-8?q?address=20already=20registred=20foundation=20API=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029991:?= =?UTF-8?q?=20THOR-99:=20Thor=20module=20build/packaging=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029994:=20?= =?UTF-8?q?Changes=20for=20THOR-92,=20THOR-93=20and=20THOR-96.=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030199:=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029995:=20?= =?UTF-8?q?THOR-93.=20Use=20the=20proper=20sspring=20config=20in=20the=20t?= =?UTF-8?q?est=20case.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2029996:=20THOR-99:=20Thor=20module=20build/?= =?UTF-8?q?packaging=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2029997:=20Consolidated=20DaveC's=20EmailAddres?= =?UTF-8?q?sService=20and=20my=20EMailUtil=20into=20a=20single=20feature.?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2029998:=20Follow-on=20to=20previous=20check-in=20(29997?= =?UTF-8?q?).=20Deletion=20of=20now-unused=20folder.=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030000:=20Bla?= =?UTF-8?q?tant=20attempt=20to=20get=20svn=20r=3D30k.=20Removing=20some=20?= =?UTF-8?q?dead=20config.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030001:=20THOR-96.=20Ensure=20that=20we?= =?UTF-8?q?=20get=20a=20meaningful=20exception=20when=20attempting=20to=20?= =?UTF-8?q?activate=20an=20account=20with=20no=20pending=20workflow=20for?= =?UTF-8?q?=20that=20email.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2030036:=20Resolve=20issues=20with=20t?= =?UTF-8?q?enant-independent=20user=20store=20-=20can=20now=20login=20via?= =?UTF-8?q?=20Share=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2030041:=20Package=20and=20auto=20deploy=20of?= =?UTF-8?q?=20license=20with=20Thor=20module=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030048:=20Ensure=20tha?= =?UTF-8?q?t=20when=20a=20duplicate=20email=20prevents=20a=20workflow=20fr?= =?UTF-8?q?om=20creating=20an=20account,=20that=20the=20workflow=20still?= =?UTF-8?q?=20ends=20gracefully.=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2030049:=20Removing=20a=20dead=20cl?= =?UTF-8?q?ass=20that=20I'd=20used=20to=20see=20how=20our=20Bamboo=20handl?= =?UTF-8?q?es=20@Ignore(message=3Dmsg)=20@Test=20annotations.=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20300?= =?UTF-8?q?54:=20THOR-84=20F82:=20List=20Accounts=20Foundation=20API=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030067:=20THOR-87=20List=20Accounts=20REST=20API.=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20300?= =?UTF-8?q?69:=20THOR-87.=20Completion=20of=20listAccounts=20REST=20API.?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20Fixed=20the=20problems=20in=20the=20JUnit?= =?UTF-8?q?=20test=20case=20and=20tweaked=20the=20FTL=20slightly.=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?30071:=20Cosmetic=20changes=20as=20part=20of=20THOR-93.=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030072:=20Oops.=20Broke=20a=20test=20case.=20Follow-on=20to?= =?UTF-8?q?=20previous=20(30071)=20check-in=20which=20cosmetically=20chang?= =?UTF-8?q?ed=20JSON=20as=20part=20of=20THOR-93.=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030073:=20As=20p?= =?UTF-8?q?art=20of=20THOR-93=20(REST=20API=20signup)=20I=20have=20made=20?= =?UTF-8?q?the=202=20webscripts=20usable=20without=20any=20authentication.?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030074:=20Trivial=20fix=20to=20an=20error=20string.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030076:=20THOR-93.=20The=20account-activation.post=20websc?= =?UTF-8?q?ript=20now=20includes=20the=20provided=20workflowInstanceId=20w?= =?UTF-8?q?hen=20identifying=20the=20ongoing=20workflow.=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030077:=20?= =?UTF-8?q?Fix=20Email=20validator=20to=20allow=20for=20example=20domains?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20302?= =?UTF-8?q?02:=20Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030140:=20Refactor=20of=20account=20signup=20workflow=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030142:=20No=20longer=20require=20email=20address=20for=20?= =?UTF-8?q?activation=20step=20of=20sign-up=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030143:=20Remove=20use?= =?UTF-8?q?=20of=20task=20query=20in=20account=20signup=20workflow=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030146:=20thor-share=20project=20structure=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030147:=20?= =?UTF-8?q?Buildfix=20(removed=20modules=20not=20used=20by=20THOR)=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030151:=20Incorporate=20already=20registered=20use=20case=20i?= =?UTF-8?q?nto=20account=20signup=20workflow=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030152:=20Finally=20re?= =?UTF-8?q?solve=20license=20loading=20in=20Eclipse=20based=20tests=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030203:=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?30184:=20Build=20box=20fix=20as=20a=20result=20of=20not=20inclu?= =?UTF-8?q?ding=20certian=20components=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030206:=20Fix=20blatant=20merge=20issues?= =?UTF-8?q?=20=20=20=2047972:=20Merged=20BRANCHES/DEV/CONV=5FV413=20to=20B?= =?UTF-8?q?RANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2046766:=20Mer?= =?UTF-8?q?ged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2035497:=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/THOR0=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2029723:=20THOR-31:=20MT-awar?= =?UTF-8?q?e=20shared=20caches=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2029749:=20THOR-5:=20MT-aware=20immutable=20single?= =?UTF-8?q?tons=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029?= =?UTF-8?q?762:=20THOR-31:=20MT-aware=20shared=20cache=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2046767:=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/?= =?UTF-8?q?DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20=20=20=20=20=2035507?= =?UTF-8?q?:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030237:=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/THOR0=20to=20BRANCHES/DEV/THOR1:=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?29532:=20THOR-79=20-=20add=20ability=20to=20disable=20Lucene=20?= =?UTF-8?q?indexes=20(so=20that=20IndexInfo=20/=20IndexInfoBackup=20files?= =?UTF-8?q?=20are=20not=20created=20per=20store=20per=20tenant)=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?29723:=20THOR-31:=20MT-aware=20shared=20caches=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029749:?= =?UTF-8?q?=20THOR-5:=20MT-aware=20immutable=20singletons=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2029762:?= =?UTF-8?q?=20THOR-31:=20MT-aware=20shared=20cache=20=20=20=2047973:=20CON?= =?UTF-8?q?V=5FHEAD:=20CLOUD-1348=20-=20comment=20back=20in=20MultiTDemoTe?= =?UTF-8?q?st=20tests=20(testNonSharedGroupDeletion=20&=20testSharedGroupD?= =?UTF-8?q?eletion)=20=20=20=2047975:=20CONV=5FHEAD:=20CLOUD-1348=20-=20co?= =?UTF-8?q?mment=20back=20in=20FeedNotifierTest.testFailedNotifications=20?= =?UTF-8?q?=20=20=2047988:=20Merged=20BRANCHES/DEV/CONV=5FV413=20to=20BRAN?= =?UTF-8?q?CHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2046775:=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2035531:=20Merged=20BRANCHES/?= =?UTF-8?q?DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030449:=20F66:=20add=20optio?= =?UTF-8?q?n=20to=20configure=20a=20common=20"contentRootContainerPath"=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030564:?= =?UTF-8?q?=20THOR-156:=20prep=20-=20consolidate=20runAsSystemTenant/runAs?= =?UTF-8?q?PrimaryTenant=20=20=20=20=20=20=20=20=20=20=20=20=20=2035532:?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030777:=20?= =?UTF-8?q?THOR-201:=20temporarily=20comment-out=20MultiTDemoTest.testDele?= =?UTF-8?q?teArchiveAndRestoreContent=20(pending=20fix=20for=20THOR-201)?= =?UTF-8?q?=20=20=20=2048008:=20Merged=20BRANCHES/DEV/CONV=5FV413=20to=20B?= =?UTF-8?q?RANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2046844:=20(RE?= =?UTF-8?q?CORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV?= =?UTF-8?q?/CONV=5FV413:=20=20=20=20=20=20=20=20=2046895:=20(RECORD=20ONLY?= =?UTF-8?q?)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV41?= =?UTF-8?q?3:=20=20=20=20=20=20=20=20=2046903:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2046907:=20(RECORD=20ONLY)=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2046922:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CL?= =?UTF-8?q?OUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2046974:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046991:?= =?UTF-8?q?=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCH?= =?UTF-8?q?ES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2046992:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CON?= =?UTF-8?q?V=5FV413:=20=20=20=20=20=20=20=20=2046994:=20(RECORD=20ONLY)=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2047107:=20(RECORD=20ONLY)=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2047265:=20(RECORD=20ONLY)=20Merged=20BRANCHES/?= =?UTF-8?q?DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2047267:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD?= =?UTF-8?q?2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2047?= =?UTF-8?q?272:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BR?= =?UTF-8?q?ANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2047277:=20(REC?= =?UTF-8?q?ORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/?= =?UTF-8?q?CONV=5FV413:=20=20=20=20=20=20=20=20=2047284:=20(RECORD=20ONLY)?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=2047286:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2047289:=20(RECORD=20ONLY)=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2047292:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CL?= =?UTF-8?q?OUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=2048009:=20Merge?= =?UTF-8?q?d=20DEV/CONV=5FV413=20to=20DEV/CONV=5FHEAD=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2046801:=20Merged=20from=20BRANCHES/DEV/CLOUD2=20to=20BRANC?= =?UTF-8?q?HES/DEV/CONV=5FV413=20=20=20=20=20=20=20=20=20=20=20=2035602:?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030513:=20Cloud=20Shar?= =?UTF-8?q?e=20module=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030515:?= =?UTF-8?q?=20Fix=20issue=20with=20person=20replication=20between=20tenant?= =?UTF-8?q?s.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030516:=20Slight?= =?UTF-8?q?=20mod=20to=20email=20validation=20web=20script=20response.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030518:=20Quick=20fix?= =?UTF-8?q?=20for=20workflow=20id=20generation=20in=20sign=20email=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030534:=20THOR-163:=20Una?= =?UTF-8?q?ble=20to=20get=20license=20file=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030535:=20Fix=20Thor=20build=20process.=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030536:=20Refine=20user's=20?= =?UTF-8?q?home=20site=20name=20and=20description=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030539:=20THOR-96.=20When=20sending=20the?= =?UTF-8?q?=20signup=20email,=20execute=20the=20mail=20action=20asynchrono?= =?UTF-8?q?usly.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030542:=20Repl?= =?UTF-8?q?ace=20placeholder=20text=20in=20sign-up=20email=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2030543:=20Account=20Activation=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2046802:=20Merged=20from=20BRANCHES/DEV/C?= =?UTF-8?q?LOUD2=20to=20BRANCHES/DEV/CONV=5FV413=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2035643:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHE?= =?UTF-8?q?S/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030544?= =?UTF-8?q?:=20Account=20activation=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030545:=20Account=20activation=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2030550:=20AMP=20build=20targets=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2030554:=20THOR-94.=20Cloud=20site?= =?UTF-8?q?=20invitation=20workflow.=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030555:=20AMP=20build=20targets=20-=20added=20client=20?= =?UTF-8?q?side=20resources=20=20=20=2048011:=20Merged=20BRANCHES/DEV/CONV?= =?UTF-8?q?=5FV413=20to=20BRANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2047056:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2?= =?UTF-8?q?=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20470?= =?UTF-8?q?87:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRA?= =?UTF-8?q?NCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2047228:=20(RECO?= =?UTF-8?q?RD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/C?= =?UTF-8?q?ONV=5FV413:=20=20=20=20=20=20=20=20=2047271:=20(RECORD=20ONLY)?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=2047297:=20(RECORD=20ONLY)=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2047299:=20(RECORD=20ONLY)=20Merged=20BRANCH?= =?UTF-8?q?ES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2047300:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CL?= =?UTF-8?q?OUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2047301:=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2047304:?= =?UTF-8?q?=20(RECORD=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCH?= =?UTF-8?q?ES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=2047328:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CON?= =?UTF-8?q?V=5FV413:=20=20=20=20=20=20=20=20=2047330:=20(RECORD=20ONLY)=20?= =?UTF-8?q?Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2047339:=20(RECORD=20ONLY)=20Merged=20?= =?UTF-8?q?BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20?= =?UTF-8?q?=2048013:=20Merged=20DEV/CONV=5FV413=20to=20DEV/CONV=5FHEAD=20(?= =?UTF-8?q?commiting=20the=20missing=20merge=20info=20for=20r48009)=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2046801:=20Merged=20from=20BRANCHES/DEV/CLOU?= =?UTF-8?q?D2=20to=20BRANCHES/DEV/CONV=5FV413=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2035602:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/D?= =?UTF-8?q?EV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030513:?= =?UTF-8?q?=20Cloud=20Share=20module=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030515:=20Fix=20issue=20with=20person=20replication=20b?= =?UTF-8?q?etween=20tenants.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=203?= =?UTF-8?q?0516:=20Slight=20mod=20to=20email=20validation=20web=20script?= =?UTF-8?q?=20response.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030518:?= =?UTF-8?q?=20Quick=20fix=20for=20workflow=20id=20generation=20in=20sign?= =?UTF-8?q?=20email=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030534:=20T?= =?UTF-8?q?HOR-163:=20Unable=20to=20get=20license=20file=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2030535:=20Fix=20Thor=20build=20proces?= =?UTF-8?q?s.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030536:=20Refine?= =?UTF-8?q?=20user's=20home=20site=20name=20and=20description=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2030539:=20THOR-96.=20When=20sen?= =?UTF-8?q?ding=20the=20signup=20email,=20execute=20the=20mail=20action=20?= =?UTF-8?q?asynchronously.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20305?= =?UTF-8?q?42:=20Replace=20placeholder=20text=20in=20sign-up=20email=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030543:=20Account=20Activ?= =?UTF-8?q?ation=20=20=20=20=20=20=20=20=2046802:=20Merged=20from=20BRANCH?= =?UTF-8?q?ES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2035643:=20Merged=20BRANCHES/DEV/THOR1=20to=20B?= =?UTF-8?q?RANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030544:=20Account=20activation=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030545:=20Account=20activation=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2030550:=20AMP=20build=20targets=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030554:=20THOR-94.=20Clou?= =?UTF-8?q?d=20site=20invitation=20workflow.=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030555:=20AMP=20build=20targets=20-=20added=20cli?= =?UTF-8?q?ent=20side=20resources=20=20=20=2048015:=20Merged=20DEV/CONV=5F?= =?UTF-8?q?V413=20to=20DEV/CONV=5FHEAD=20=20=20=20=20=20=20=20=2046841:=20?= =?UTF-8?q?Merged=20from=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5F?= =?UTF-8?q?V413=20=20=20=20=20=20=20=20=20=20=20=2035684:=20Merged=20BRANC?= =?UTF-8?q?HES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030904:=20(RECORD=20ONLY)=20Merged=20HEA?= =?UTF-8?q?D=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030270=20=20ALF-9492=20Can=20now=20update?= =?UTF-8?q?=20task=20properties=20through=20the=20Workflow=20JavaScript=20?= =?UTF-8?q?API.=20ALF-10087=20Fixed=20failing=20Multi-tenancy=20tests.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030288=20=20A?= =?UTF-8?q?LF-9492=20Can=20now=20update=20task=20properties=20through=20th?= =?UTF-8?q?e=20Workflow=20JavaScript=20API.=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030309=20=20Fixed=20failing=20MultiTDemo?= =?UTF-8?q?Test=20and=20re-enabled.=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030356=20=20ALF-10117:=20JBPM=20workflows=20shoul?= =?UTF-8?q?d=20be=20hidden.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030358=20=20Build=20fix,=20fallout=20from=20ALF-10117?= =?UTF-8?q?=20(JBPM=20workflows=20should=20be=20hidden)=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030415=20=20Added=20parseRoo?= =?UTF-8?q?tElement()=20method=20to=20Activiti's=20BPMNParseListener.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030452=20=20A?= =?UTF-8?q?LF-10276:=20Reject=20flow=20didn't=20set=20bpm=5Fassignee=20pro?= =?UTF-8?q?perty=20properly=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030563=20=20Added=20tests=20to=20ensure=20multi-tenancy?= =?UTF-8?q?=20works=20and=20fixed=20several=20multi-tenancy=20issues=20in?= =?UTF-8?q?=20workflow.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030698=20=20ALF-9541:=20Fixed=20HistoricTaskEntity=20update?= =?UTF-8?q?=20when=20TaskEntity=20is=20loaded=20from=20DB=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030699=20=20ALF-10084,=20?= =?UTF-8?q?ALF-10242.=20Fixed=20issues=20and=20added=20WorkflowService=20m?= =?UTF-8?q?ethods=20to=20get=20workflow=20instances=20without=20filtering?= =?UTF-8?q?=20by=20definition=20id.=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030750=20=20ALF-10197,=20Added=20the=20ability=20?= =?UTF-8?q?to=20auto-complete=20Start=20Tasks=20in=20Activiti.=20If=20a=20?= =?UTF-8?q?start=20task=20extends=20the=20bpm:activitiStartTask=20type=20o?= =?UTF-8?q?r=20implements=20the=20bpm:endAutomatically=20aspect=20then=20t?= =?UTF-8?q?he=20task=20will=20be=20ended=20as=20soon=20as=20the=20workflow?= =?UTF-8?q?=20instance=20is=20started.=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2030796=20=20ALF-10374=20Fixed=20failing=20Mult?= =?UTF-8?q?iTDemoTest=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030908:?= =?UTF-8?q?=20Add=20logging=20for=20failed=20email=20domain=20lookups:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030922:=20Rolling=20ba?= =?UTF-8?q?ck=20.classpath=20changes=20to=20Data=20Model.=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2030930:=20Basic=20version=20of=20s?= =?UTF-8?q?ite=20invite=20working=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030931:=20THOR-172:=20Switch=20Tenant=20via=20public=20API?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030936:=20Allow=20f?= =?UTF-8?q?or=20repo=20web=20scripts=20to=20switch=20to=20user's=20default?= =?UTF-8?q?=20tenant=20via=20-default-=20tenant=20id:=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030937:=20Implementation=20of=20THOR-214?= =?UTF-8?q?.=20There=20is=20now=20a=20new=20repo=20webscript=20to=20retrie?= =?UTF-8?q?ve=20signup=20status=20for=20a=20given=20{id,=20key}=20pair.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030938:=20Allow=20dev?= =?UTF-8?q?=20email=20address=20to=20be=20specified=20in=20properties=20fi?= =?UTF-8?q?le:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030945:=20THOR-2?= =?UTF-8?q?21:=20Add=20(EntityLookup)=20cache=20to=20AccountDAO=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030946:=20Build=20fix.=20Ren?= =?UTF-8?q?aming=20a=20test=20infrastructure=20class=20so=20that=20it=20do?= =?UTF-8?q?esn't=20get=20picked=20up=20by=20the=20ant=20test=20targets.=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030955:=20THOR-222.=20?= =?UTF-8?q?Added=20inviter=20first=20and=20last=20name=20to=20invitation-s?= =?UTF-8?q?tatus.get=20webscript.=20=20=20=20=20=20=20=20=2046843:=20Merge?= =?UTF-8?q?d=20from=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2035694:=20Merged=20BRANCHES/?= =?UTF-8?q?DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030997:=20Firefox=20scrollbars=20removed=20?= =?UTF-8?q?on=20"invitation"=20and=20"signup"=20pages=20(now=20using=20new?= =?UTF-8?q?=20helper=20method=20Alfresco.util.createYUIOverlay)=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2031001:=20Impl=20of=20THOR-2?= =?UTF-8?q?23.=20Webscripts=20for=20getting=20pending=20invitations.=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2031002:=20Invite=20-=20re?= =?UTF-8?q?direct=20bug=20fixed,=20removed=20old=20code=20matching=20previ?= =?UTF-8?q?ous=20webscript=20api,=20email=20picker=20style=20fixes=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2031003:=20Addendum=20for?= =?UTF-8?q?=20THOR-223.=20I've=20added=20an=20explicit=20test=20to=20recor?= =?UTF-8?q?d=20the=20fact=20that=20pending-invitations.get=20to=20a=20non-?= =?UTF-8?q?existent=20site=20returns=20200=20and=20an=20empty=20collection?= =?UTF-8?q?=20rather=20than=20a=20404.=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2031004:=20Adding=20REST-client=20.rcq=20files=20as=20pa?= =?UTF-8?q?rt=20of=20THOR-223=20=20=20=20=20=20=20=20=2046848:=20Merged=20?= =?UTF-8?q?from=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2035700:=20Merged=20BRANCHES/DEV?= =?UTF-8?q?/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2031014:=20(RECORD=20ONLY)=20Merged=20HEAD=20to?= =?UTF-8?q?=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030999:=20ALF-9957=20-=20MT:=20test=20and?= =?UTF-8?q?=20fix=20subscriptions=20(followers)=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2031020:=20Update=20invite=20email=20template?= =?UTF-8?q?=20to=20bring=20in=20line=20with=20wireframe=20and=20text=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2031021:=20Apply=20latest?= =?UTF-8?q?=20sanitized=20email=20blacklist:=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2031030:=20Fixed=20THOR-226=20"DocLib=20"Detailed?= =?UTF-8?q?=20View"=20(default)=20does=20not=20list=20items=20-=20note:=20?= =?UTF-8?q?"Simple=20View"=20seems=20to=20be=20OK"=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2031033:=20THOR-228:=20Update=20aws=20sample?= =?UTF-8?q?=20file=20with=20quota=20config=20for=20cachingcontentstore=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2031036:=20Fixed=20THOR?= =?UTF-8?q?-236=20"Webscript=20URL=20clash=20in=20signup"=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2031037:=20THOR-175:=20set=20and=20?= =?UTF-8?q?enforce=20per-tenant=20quota=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2031043:=20Fixed=20THOR-174=20"F27:=20User=20can=20sw?= =?UTF-8?q?itch=20between=20networks=20they=20belong=20to"=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2046854:=20Merged=20from=20BRANCHES/DEV/CLOUD2=20to?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FV413=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?35725:=20Merged=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2031124:=20Fix=20fo?= =?UTF-8?q?r=20THOR-145.=20This=20check-in=20makes=20the=20Cloud=20Signup?= =?UTF-8?q?=20and=20Invitation=20workflows=20hidden=20within=20Share=20-?= =?UTF-8?q?=20users=20can't=20initiate=20them=20via=20"Start=20workflow...?= =?UTF-8?q?"=20=20=20=2048016:=20Merged=20BRANCHES/DEV/CONV=5FV413=20to=20?= =?UTF-8?q?BRANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2046793:=20Me?= =?UTF-8?q?rged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2046795:=20Merged=20BRANCHES/DEV/CLOUD2?= =?UTF-8?q?=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20467?= =?UTF-8?q?96:=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV?= =?UTF-8?q?413:=20=20=20=2048030:=20Merged=20BRANCHES/DEV/CONV=5FV413=20to?= =?UTF-8?q?=20BRANCHES/DEV/CONV=5FHEAD:=20=20=20=20=20=20=20=20=2046820:?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413?= =?UTF-8?q?:=20=20=20=20=20=20=20=20=20=20=20=20=20=2035657:=20Merged=20BR?= =?UTF-8?q?ANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030556:=20THOR-135F103:?= =?UTF-8?q?=20Is=20e-mail=20address=20accepted=20by=20Alfresco=3F=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030562:=20Fixing?= =?UTF-8?q?=20a=20typo=20in=20the=20email-validation=20FTL.=20It=20was=20r?= =?UTF-8?q?eturning=20invalid=20JSON=20-=20no=20opening=20"=20on=20a=20str?= =?UTF-8?q?ing.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030?= =?UTF-8?q?569:=20THOR-156:=20switch=20to=20secondary=20tenant=20(initiall?= =?UTF-8?q?y=20via=20@@login)=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030571:=20THOR-99:=20Thor=20build=20=20=20=2048037:?= =?UTF-8?q?=20Merged=20BRANCHES/DEV/CONV=5FV413=20to=20BRANCHES/DEV/CONV?= =?UTF-8?q?=5FHEAD:=20=20=20=20=20=20=20=20=2046821:=20Merged=20BRANCHES/D?= =?UTF-8?q?EV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2035659:=20Merged=20BRANCHES/DEV/THOR1=20to?= =?UTF-8?q?=20BRANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2030586:=20THOR-166.=20I've=20added=20an=20addi?= =?UTF-8?q?tional=20check=20at=20the=20start=20of=20the=20signup=20workflo?= =?UTF-8?q?w=20that=20checks=20if=20the=20email=20is=20blocked.=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030587:=20THOR-1?= =?UTF-8?q?63:=20S3ContentReader=20fails=20to=20getObjectDetails=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030592:=20THOR-1?= =?UTF-8?q?56:=20switch=20to=20secondary=20tenant=20(initially=20via=20@@l?= =?UTF-8?q?ogin)=20=20=20=20=20=20=20=20=20=20=20=20=20=2035660:=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030607:=20(RECORD?= =?UTF-8?q?=20ONLY)=20Merged=20HEAD=20to=20BRANCHES/DEV/THOR1:=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20302?= =?UTF-8?q?08:=20Remaining=20commits=20for=20ALF-9510=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030218:=20Fix?= =?UTF-8?q?=20build=20-=20add=20missing=20files=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030254:=20Encryptio?= =?UTF-8?q?n=20related=20documentation,=20source=20code=20comments=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030392:=20Fix=20for=20ALF-10205=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030405:=20Fix=20for=20?= =?UTF-8?q?ALF-10189=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2030406:=20Fix=20for=20ALF-10189:=20part=202=20?= =?UTF-8?q?-=20minor=20update=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2030613:=20THOR-148.=20The=20cloud=20test=20target=20?= =?UTF-8?q?was=20accidentally=20excluding=20*RestTest.java.=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=2030613:=20THOR-148.=20?= =?UTF-8?q?The=20cloud=20test=20target=20was=20accidentally=20excluding=20?= =?UTF-8?q?*RestTest.java.=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030614:=20Revert=20some=20of=20the=20additional=20email?= =?UTF-8?q?=20checks=20in=20registration=20process=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2030615:=20Set=20ignore=20patter?= =?UTF-8?q?ns=20for=20build=20dir=20in=20thor=20module=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=2030619:=20Merged=20HEAD?= =?UTF-8?q?=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030618:=20Additional=20test?= =?UTF-8?q?=20classes=20that=20allow=20for=20easier=20testing=20of=20Notif?= =?UTF-8?q?ications=20(emails=20mostly).=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030622:=20Ensure=20use=20of=20System=20u?= =?UTF-8?q?ser,=20not=20system=20user=20=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030624:=20Removed=20deep=20merge=20info=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030625:=20?= =?UTF-8?q?Switch=20off=20creation=20of=20missing=20people,=20use=20Admin?= =?UTF-8?q?=20instead=20of=20System=20=20=20=20=20=20=20=20=2046824:=20Mer?= =?UTF-8?q?ged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV413:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2046828:=20Merged=20BRANCHES/DEV/CLOUD2?= =?UTF-8?q?=20to=20BRANCHES/DEV/CONV=5FV413:=20=20=20=2048038:=20Merged=20?= =?UTF-8?q?DEV/CONV=5FV413=20to=20DEV/CONV=5FHEAD=20(ui-only)=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2046830:=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRA?= =?UTF-8?q?NCHES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20=20=20=20Merge?= =?UTF-8?q?d=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=2030737:=20(RECORD=20ONLY)=20Merged=20HEA?= =?UTF-8?q?D=20to=20BRANCHES/DEV/THOR1:=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=2030736:=20ALF-6706=20-=20MT:=20activities=20no?= =?UTF-8?q?t=20generated=20(for=20tenants)=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030738:=20Site=20invite=20(rough=20version,=20not=20finish?= =?UTF-8?q?ed)=20=20=20=20=20=20=20=20=20=20=20=2030741:=20THOR-175:=20Set?= =?UTF-8?q?=20and=20enforce=20file=20space=20quota=20for=20tenant=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=2030752:=20Site=20invite=20-=20added?= =?UTF-8?q?=20som=20padding=20to=20user=20suggestion=20list=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030753:=20Disabling=202=20tests=20while=20I?= =?UTF-8?q?=20fix=20them.=20=20=20=20=20=20=20=20=20=20=20=2030758:=20THOR?= =?UTF-8?q?-172=20F63:=20Switch=20Tenant=20via=20public=20REST=20API:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2030764:=20Tweak=20to=20Activiti?= =?UTF-8?q?=20integration=20code=20to=20prevent=20it=20from=20trying=20to?= =?UTF-8?q?=20create=20person=20nodes=20for=20the=20System=20user.=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=2030766:=20Implementation=20of=20TH?= =?UTF-8?q?OR-196.=20Inviting=20multiple=20email=20addresses=20in=20a=20si?= =?UTF-8?q?ngle=20call.=20=20=20=20=20=20=20=20=20=20=20=2030769:=20Re-ena?= =?UTF-8?q?ble=20MultiTDemoTest=20=20=20=20=20=20=20=20=20=20=20=2030775:?= =?UTF-8?q?=20Site=20invite=20=20=20=20=20=20=20=20=20=20=20=2030776:=20TH?= =?UTF-8?q?OR-172:=20Switch=20Tenant=20via=20public=20API=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030785:=20Add=20tenant=20id=20to=20account?= =?UTF-8?q?=20info=20returned=20in=20Thor=20responses=20=20=20=2048043:=20?= =?UTF-8?q?Merged=20DEV/CONV=5FV413=20to=20DEV/CONV=5FHEAD=20=20=20=20=20?= =?UTF-8?q?=20=20=20=2046831:=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCH?= =?UTF-8?q?ES/DEV/CONV=5FV413:=20=20=20=20=20=20=20=20=20=20=20=20Merged?= =?UTF-8?q?=20BRANCHES/DEV/THOR1=20to=20BRANCHES/DEV/CLOUD1:=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2030813:=20Add=20Eclipse=20proje?= =?UTF-8?q?ct=20for=20Thor-Share=20module:=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030815:=20THOR-175:=20Set=20and=20enforce=20file?= =?UTF-8?q?=20space=20quota=20for=20tenant=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=2030817:=20Switch=20network=20skeleton=20code=20an?= =?UTF-8?q?d=20minor=20fixes=20=20=20=20=20=20=20=20=20=20=20=20=20=20=203?= =?UTF-8?q?0818:=20Update=20Share=20Node=20Browser=20(at=20least=20for=20T?= =?UTF-8?q?HOR)=20to=20allow=20option=20to=20retrieve=20"storeroot"=20via?= =?UTF-8?q?=20DB=20query=20=20=20=20=20=20=20=20=20=20=20=20=20=20=2030826?= =?UTF-8?q?:=20Add=20distribute-solr=20to=20Thor=20builds=20=20=20=2048045?= =?UTF-8?q?:=20Merged=20BRANCHES/DEV/CLOUD2=20to=20BRANCHES/DEV/CONV=5FV41?= =?UTF-8?q?3:=20=20=20=20=20=20=20=20Merged=20BRANCHES/DEV/THOR1=20to=20BR?= =?UTF-8?q?ANCHES/DEV/CLOUD1:=20=20=20=20=20=20=20=20=20=20=20=2030737:=20?= =?UTF-8?q?(RECORD=20ONLY)=20Merged=20HEAD=20to=20BRANCHES/DEV/THOR1:=20?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=2030736:=20ALF-6706=20-=20MT:=20?= =?UTF-8?q?activities=20not=20generated=20(for=20tenants)=20=20=20=20=20?= =?UTF-8?q?=20=20=20=20=20=20=2030738:=20Site=20invite=20(rough=20version,?= =?UTF-8?q?=20not=20finished)=20=20=20=20=20=20=20=20=20=20=20=2030741:=20?= =?UTF-8?q?THOR-175:=20Set=20and=20enforce=20file=20space=20quota=20for=20?= =?UTF-8?q?tenant=20=20=20=20=20=20=20=20=20=20=20=2030752:=20Site=20invit?= =?UTF-8?q?e=20-=20added=20som=20padding=20to=20user=20suggestion=20list?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030753:=20Disabling=202=20te?= =?UTF-8?q?sts=20while=20I=20fix=20them.=20=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=2030758:=20THOR-172=20F63:=20Switch=20Tenant=20via=20public=20?= =?UTF-8?q?REST=20API:=20=20=20=20=20=20=20=20=20=20=20=2030764:=20Tweak?= =?UTF-8?q?=20to=20Activiti=20integration=20code=20to=20prevent=20it=20fro?= =?UTF-8?q?m=20trying=20to=20create=20person=20nodes=20for=20the=20System?= =?UTF-8?q?=20user.=20=20=20=20=20=20=20=20=20=20=20=2030766:=20Implementa?= =?UTF-8?q?tion=20of=20THOR-196.=20Inviting=20multiple=20email=20addresses?= =?UTF-8?q?=20in=20a=20single=20call.=20=20=20=20=20=20=20=20=20=20=20=203?= =?UTF-8?q?0769:=20Re-enable=20MultiTDemoTest=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=20=2030775:=20Site=20invite=20=20=20=20=20=20=20=20=20=20?= =?UTF-8?q?=20=2030776:=20THOR-172:=20Switch=20Tenant=20via=20public=20API?= =?UTF-8?q?=20=20=20=20=20=20=20=20=20=20=20=2030785:=20Add=20tenant=20id?= =?UTF-8?q?=20to=20account=20info=20returned=20in=20Thor=20responses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@48251 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco/repository/tenant/tenant.lib.ftl | 7 + .../repository/tenant/tenants.delete.desc.xml | 18 + .../repository/tenant/tenants.delete.json.ftl | 1 + .../repository/tenant/tenants.get.desc.xml | 16 + .../repository/tenant/tenants.get.json.ftl | 10 + .../repository/tenant/tenants.post.desc.xml | 22 + .../repository/tenant/tenants.post.json.ftl | 1 + .../alfresco/repository/upload/upload.post.js | 5 + .../web-scripts-application-context.xml | 33 +- .../repo/web/scripts/BaseWebScriptTest.java | 4 +- .../repo/web/scripts/RepositoryContainer.java | 140 +----- .../scripts/TenantRepositoryContainer.java | 131 ++++++ .../web/scripts/TenantWebScriptServlet.java | 74 ++++ .../TenantWebScriptServletRequest.java | 104 +++++ .../TenantWebScriptServletRuntime.java | 100 +++++ .../web/scripts/invite/InviteByTicket.java | 10 +- .../web/scripts/invite/InviteResponse.java | 8 +- .../tenant/AbstractTenantAdminWebScript.java | 40 ++ .../scripts/tenant/TenantAdminSystemTest.java | 405 ++++++++++++++++++ .../repo/web/scripts/tenant/TenantDelete.java | 52 +++ .../repo/web/scripts/tenant/TenantPost.java | 87 ++++ .../repo/web/scripts/tenant/TenantsGet.java | 59 +++ .../web/scripts/NodeBrowserScript.java | 31 +- 23 files changed, 1208 insertions(+), 150 deletions(-) create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenant.lib.ftl create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.desc.xml create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.json.ftl create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.desc.xml create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.json.ftl create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.desc.xml create mode 100644 config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.json.ftl create mode 100644 source/java/org/alfresco/repo/web/scripts/TenantRepositoryContainer.java create mode 100644 source/java/org/alfresco/repo/web/scripts/TenantWebScriptServlet.java create mode 100644 source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRequest.java create mode 100644 source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRuntime.java create mode 100644 source/java/org/alfresco/repo/web/scripts/tenant/AbstractTenantAdminWebScript.java create mode 100644 source/java/org/alfresco/repo/web/scripts/tenant/TenantAdminSystemTest.java create mode 100644 source/java/org/alfresco/repo/web/scripts/tenant/TenantDelete.java create mode 100644 source/java/org/alfresco/repo/web/scripts/tenant/TenantPost.java create mode 100644 source/java/org/alfresco/repo/web/scripts/tenant/TenantsGet.java diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenant.lib.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenant.lib.ftl new file mode 100644 index 0000000000..3b18ffb51e --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenant.lib.ftl @@ -0,0 +1,7 @@ +<#macro tenantJSON tenant> + { + "tenantDomain": "${tenant.tenantDomain}", + "enabled": "${tenant.enabled?string}", + "contentRoot": "${tenant.rootContentStoreDir!""}" + } + diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.desc.xml new file mode 100644 index 0000000000..15e348deb5 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.desc.xml @@ -0,0 +1,18 @@ + + Delete Tenant + The repository must be configured such that Multi-Tenancy is enabled. +
You must have "administrator" privileges to delete a tenant. + +
WARNING: This operation cannot be recovered !!! + ]]> +
+ /api/tenants/{tenantDomain} + argument + admin + required + draft_public_api + MultiTenantAdmin +
\ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.json.ftl new file mode 100644 index 0000000000..124ee87b86 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.delete.json.ftl @@ -0,0 +1 @@ +<#import "tenant.lib.ftl" as tenantLib/> \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.desc.xml new file mode 100644 index 0000000000..f79d0a6207 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.desc.xml @@ -0,0 +1,16 @@ + + Get Tenants + The repository must be in Multi-Tenant mode (1st tenant created). +
You must have "administrator" privileges to get list of tenants. + ]]> +
+ /api/tenants + argument + admin + required + draft_public_api + MultiTenantAdmin +
\ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.json.ftl new file mode 100644 index 0000000000..d753794629 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.get.json.ftl @@ -0,0 +1,10 @@ +<#import "tenant.lib.ftl" as tenantLib/> +{ + "tenants" : + [ + <#list tenants as tenant> + <@tenantLib.tenantJSON tenant=tenant/> + <#if tenant_has_next>, + + ] +} \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.desc.xml b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.desc.xml new file mode 100644 index 0000000000..91fcaf1af1 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.desc.xml @@ -0,0 +1,22 @@ + + Create Tenant + The repository must be in Multi-Tenant mode (1st tenant created). +
You must have "administrator" privileges to create a tenant. + +
+
tenantDomain
mandatory
+
tenantAdminPassword
mandatory
+
tenantContentStoreRoot
optional
+
+ ]]> +
+ /api/tenants + argument + admin + required + draft_public_api + MultiTenantAdmin +
\ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.json.ftl b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.json.ftl new file mode 100644 index 0000000000..124ee87b86 --- /dev/null +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/tenant/tenants.post.json.ftl @@ -0,0 +1 @@ +<#import "tenant.lib.ftl" as tenantLib/> \ No newline at end of file diff --git a/config/alfresco/templates/webscripts/org/alfresco/repository/upload/upload.post.js b/config/alfresco/templates/webscripts/org/alfresco/repository/upload/upload.post.js index d72633b475..cc99b0e219 100644 --- a/config/alfresco/templates/webscripts/org/alfresco/repository/upload/upload.post.js +++ b/config/alfresco/templates/webscripts/org/alfresco/repository/upload/upload.post.js @@ -345,6 +345,11 @@ function main() // Also perform the encoding guess step in the write() method to save an additional Writer operation. newFile.properties.content.write(content, false, true); newFile.save(); + + + // TODO (THOR-175) - review + // Ensure the file is versionable (autoVersion = true, autoVersionProps = false) + newFile.ensureVersioningEnabled(true, false); // NOTE: Removal of first request for thumbnails to improve upload performance // Thumbnails are still requested by Share on first render of the doclist image. diff --git a/config/alfresco/web-scripts-application-context.xml b/config/alfresco/web-scripts-application-context.xml index f952cc4806..8c5743e058 100644 --- a/config/alfresco/web-scripts-application-context.xml +++ b/config/alfresco/web-scripts-application-context.xml @@ -137,7 +137,7 @@ js - + Repository @@ -1873,8 +1873,7 @@ - - + @@ -1950,4 +1949,32 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/source/java/org/alfresco/repo/web/scripts/BaseWebScriptTest.java b/source/java/org/alfresco/repo/web/scripts/BaseWebScriptTest.java index 767ac4d218..e010607ee7 100644 --- a/source/java/org/alfresco/repo/web/scripts/BaseWebScriptTest.java +++ b/source/java/org/alfresco/repo/web/scripts/BaseWebScriptTest.java @@ -151,7 +151,7 @@ public abstract class BaseWebScriptTest extends TestCase * Sets custom context for Test Web Script Server (in-process only) * @param customContext */ - protected void setCustomContext(String customContext) + public void setCustomContext(String customContext) { this.customContext = customContext; } @@ -254,7 +254,7 @@ public abstract class BaseWebScriptTest extends TestCase /** * Get the server for the previously-supplied {@link #setCustomContext(String) custom context} */ - protected TestWebScriptServer getServer() + public TestWebScriptServer getServer() { TestWebScriptServer server; if (customContext == null) diff --git a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java index 3b45b42a73..6479067bba 100644 --- a/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java +++ b/source/java/org/alfresco/repo/web/scripts/RepositoryContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2012 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -30,20 +30,15 @@ import java.io.OutputStream; import java.io.Writer; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.servlet.http.HttpServletResponse; import javax.transaction.Status; import javax.transaction.UserTransaction; import org.alfresco.error.AlfrescoRuntimeException; -import org.alfresco.repo.cache.SimpleCache; import org.alfresco.repo.model.Repository; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.repo.tenant.TenantAdminService; -import org.alfresco.repo.tenant.TenantDeployer; import org.alfresco.repo.transaction.AlfrescoTransactionSupport; import org.alfresco.repo.transaction.AlfrescoTransactionSupport.TxnReadState; import org.alfresco.repo.transaction.RetryingTransactionHelper; @@ -57,7 +52,6 @@ import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.TempFileProvider; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.springframework.beans.factory.ObjectFactory; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationEvent; import org.springframework.context.event.ContextRefreshedEvent; @@ -73,7 +67,6 @@ import org.springframework.extensions.webscripts.Description.RequiredTransaction import org.springframework.extensions.webscripts.Description.RequiredTransactionParameters; import org.springframework.extensions.webscripts.Description.TransactionCapability; import org.springframework.extensions.webscripts.Match; -import org.springframework.extensions.webscripts.Registry; import org.springframework.extensions.webscripts.Runtime; import org.springframework.extensions.webscripts.ServerModel; import org.springframework.extensions.webscripts.WebScript; @@ -90,7 +83,7 @@ import org.springframework.util.FileCopyUtils; * * @author davidc */ -public class RepositoryContainer extends AbstractRuntimeContainer implements TenantDeployer +public class RepositoryContainer extends AbstractRuntimeContainer { // Logger protected static final Log logger = LogFactory.getLog(RepositoryContainer.class); @@ -102,28 +95,7 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten private RetryingTransactionHelper fallbackTransactionHelper; private AuthorityService authorityService; private DescriptorService descriptorService; - private TenantAdminService tenantAdminService; - private ObjectFactory registryFactory; - private SimpleCache webScriptsRegistryCache; - private ReadWriteLock webScriptsRegistryLock = new ReentrantReadWriteLock(); - private boolean initialized; - /** - * @param webScriptsRegistryCache - */ - public void setWebScriptsRegistryCache(SimpleCache webScriptsRegistryCache) - { - this.webScriptsRegistryCache = webScriptsRegistryCache; - } - - /** - * @param registryFactory - */ - public void setRegistryFactory(ObjectFactory registryFactory) - { - this.registryFactory = registryFactory; - } - /** * @param repository */ @@ -172,14 +144,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten this.authorityService = authorityService; } - /** - * @param tenantAdminService - */ - public void setTenantAdminService(TenantAdminService tenantAdminService) - { - this.tenantAdminService = tenantAdminService; - } - /* (non-Javadoc) * @see org.alfresco.web.scripts.Container#getDescription() */ @@ -546,51 +510,6 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten } } - /* (non-Javadoc) - * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRegistry() - */ - @Override - public Registry getRegistry() - { - String tenantDomain = tenantAdminService.getCurrentUserDomain(); - Registry registry; - webScriptsRegistryLock.readLock().lock(); - try - { - registry = webScriptsRegistryCache.get(tenantDomain); - } - finally - { - webScriptsRegistryLock.readLock().unlock(); - } - if (registry == null) - { - webScriptsRegistryLock.writeLock().lock(); - try - { - // Double check now we have write lock - registry = webScriptsRegistryCache.get(tenantDomain); - - // Initialize / reinitialize the registry in this thread only - if (registry == null) - { - registry = (Registry) registryFactory.getObject(); - // We only need to reset the registry if the superclass thinks its already initialized - if (initialized) - { - registry.reset(); - } - webScriptsRegistryCache.put(tenantDomain, registry); - } - } - finally - { - webScriptsRegistryLock.writeLock().unlock(); - } - } - return registry; - } - /* (non-Javadoc) * @see org.alfresco.web.scripts.AbstractRuntimeContainer#onApplicationEvent(org.springframework.context.ApplicationEvent) */ @@ -656,68 +575,17 @@ public class RepositoryContainer extends AbstractRuntimeContainer implements Ten { public Object execute() throws Exception { - destroy(); - init(); - + internalReset(); return null; } }, true, false); } - /* (non-Javadoc) - * @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant() - */ - public void onEnableTenant() + private void internalReset() { - init(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant() - */ - public void onDisableTenant() - { - destroy(); - } - - /* (non-Javadoc) - * @see org.alfresco.repo.tenant.TenantDeployer#init() - */ - public void init() - { - tenantAdminService.register(this); - super.reset(); - - initialized = true; } - /* (non-Javadoc) - * @see org.alfresco.repo.tenant.TenantDeployer#destroy() - */ - public void destroy() - { - try - { - webScriptsRegistryLock.writeLock().lock(); - webScriptsRegistryCache.remove(tenantAdminService.getCurrentUserDomain()); - - if (logger.isTraceEnabled()) - { - Exception e = new Exception("RepositoryContainer destroy called."); - e.fillInStackTrace(); - logger.trace("", e); - } - } - finally - { - webScriptsRegistryLock.writeLock().unlock(); - } - - initialized = false; - } - - /** * Transactional Buffered Response */ diff --git a/source/java/org/alfresco/repo/web/scripts/TenantRepositoryContainer.java b/source/java/org/alfresco/repo/web/scripts/TenantRepositoryContainer.java new file mode 100644 index 0000000000..c416f1e0c0 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/TenantRepositoryContainer.java @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2005-2010 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts; + +import org.alfresco.repo.cache.SimpleCache; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.tenant.TenantAdminService; +import org.alfresco.repo.tenant.TenantDeployer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.ObjectFactory; +import org.springframework.extensions.webscripts.Description.RequiredAuthentication; +import org.springframework.extensions.webscripts.Registry; + + +/** + * Tenant-aware Repository (server-tier) container for Web Scripts + * + * @author davidc + */ +public class TenantRepositoryContainer extends RepositoryContainer implements TenantDeployer +{ + // Logger + protected static final Log logger = LogFactory.getLog(TenantRepositoryContainer.class); + + /** Component Dependencies */ + private TenantAdminService tenantAdminService; + private ObjectFactory registryFactory; + private SimpleCache webScriptsRegistryCache; + private boolean initialized; + + /** + * @param webScriptsRegistryCache + */ + public void setWebScriptsRegistryCache(SimpleCache webScriptsRegistryCache) + { + this.webScriptsRegistryCache = webScriptsRegistryCache; + } + + /** + * @param registryFactory + */ + public void setRegistryFactory(ObjectFactory registryFactory) + { + this.registryFactory = registryFactory; + } + + /** + * @param tenantAdminService + */ + public void setTenantAdminService(TenantAdminService tenantAdminService) + { + this.tenantAdminService = tenantAdminService; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.AbstractRuntimeContainer#getRegistry() + */ + @Override + public Registry getRegistry() + { + String tenantDomain = tenantAdminService.getCurrentUserDomain(); + Registry registry = webScriptsRegistryCache.get(tenantDomain); + if (registry == null) + { + registry = (Registry)registryFactory.getObject(); + // We only need to reset the registry if the superclass thinks its already initialized + if (initialized) + { + registry.reset(); + } + webScriptsRegistryCache.put(tenantDomain, registry); + } + return registry; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.tenant.TenantDeployer#onEnableTenant() + */ + public void onEnableTenant() + { + init(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.tenant.TenantDeployer#onDisableTenant() + */ + public void onDisableTenant() + { + destroy(); + } + + /* (non-Javadoc) + * @see org.alfresco.repo.tenant.TenantDeployer#init() + */ + public void init() + { + tenantAdminService.register(this); + + super.reset(); + + initialized = true; + } + + /* (non-Javadoc) + * @see org.alfresco.repo.tenant.TenantDeployer#destroy() + */ + public void destroy() + { + webScriptsRegistryCache.remove(tenantAdminService.getCurrentUserDomain()); + + initialized = false; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServlet.java b/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServlet.java new file mode 100644 index 0000000000..5dce253113 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServlet.java @@ -0,0 +1,74 @@ +/** + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This file is part of the Spring Surf Extension project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.alfresco.repo.web.scripts; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.surf.util.I18NUtil; +import org.springframework.extensions.webscripts.servlet.WebScriptServlet; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; + + +/** + * Entry point for web scripts which can accept a tenant id in their servlet path + * + * @author davidc + */ +public class TenantWebScriptServlet extends WebScriptServlet +{ + public static final String DEFAULT_TENANT = "-default-"; + + private static final long serialVersionUID = 2954663814419046489L; + + // Logger + private static final Log logger = LogFactory.getLog(TenantWebScriptServlet.class); + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + protected void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException + { + if (logger.isDebugEnabled()) + logger.debug("Processing tenant request (" + req.getMethod() + ") " + req.getRequestURL() + (req.getQueryString() != null ? "?" + req.getQueryString() : "")); + + if (req.getCharacterEncoding() == null) + { + req.setCharacterEncoding("UTF-8"); + } + + setLanguageFromRequestHeader(req); + + try + { + WebScriptServletRuntime runtime = new TenantWebScriptServletRuntime(container, authenticatorFactory, req, res, serverProperties); + runtime.executeScript(); + } + finally + { + // clear threadlocal + I18NUtil.setLocale(null); + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRequest.java b/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRequest.java new file mode 100644 index 0000000000..16c7ec9082 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRequest.java @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This file is part of the Spring Surf Extension project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.alfresco.repo.web.scripts; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.extensions.config.ServerProperties; +import org.springframework.extensions.surf.util.URLDecoder; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.Runtime; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRequest; + + +/** + * Web Script Request which can handle a tenant id in their servlet path + * + * @author davidc + */ +public class TenantWebScriptServletRequest extends WebScriptServletRequest +{ + private String tenant; + private String pathInfo; + + /** + * Construction + * + * @param container request generator + * @param req + * @param serviceMatch + */ + public TenantWebScriptServletRequest(Runtime container, HttpServletRequest req, Match serviceMatch, ServerProperties serverProperties) + { + super(container, req, serviceMatch, serverProperties); + + String realPathInfo = getRealPathInfo(); + + // remove tenant + int idx = realPathInfo.indexOf('/', 1); + tenant = realPathInfo.substring(1, idx == -1 ? realPathInfo.length() : idx); + pathInfo = realPathInfo.substring(tenant.length() + 1); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRequest#getServiceContextPath() + */ + public String getServiceContextPath() + { + return getHttpServletRequest().getContextPath() + getHttpServletRequest().getServletPath() + "/" + tenant; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo() + */ + public String getPathInfo() + { + return pathInfo; + } + + public String getTenant() + { + return tenant; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRequest#getPathInfo() + */ + private String getRealPathInfo() + { + // NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat + final String requestURI = getHttpServletRequest().getRequestURI(); + final String serviceContextPath = getHttpServletRequest().getContextPath() + getHttpServletRequest().getServletPath(); + String pathInfo; + + if (serviceContextPath.length() > requestURI.length()) + { + // NOTE: assume a redirect has taken place e.g. tomcat welcome-page + // NOTE: this is unlikely, and we'll take the hit if the path contains a semi-colon + pathInfo = getHttpServletRequest().getPathInfo(); + } + else + { + pathInfo = URLDecoder.decode(requestURI.substring(serviceContextPath.length())); + } + + return pathInfo; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRuntime.java b/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRuntime.java new file mode 100644 index 0000000000..f5be0ecf00 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/TenantWebScriptServletRuntime.java @@ -0,0 +1,100 @@ +/** + * Copyright (C) 2005-2009 Alfresco Software Limited. + * + * This file is part of the Spring Surf Extension project. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.alfresco.repo.web.scripts; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.extensions.config.ServerProperties; +import org.springframework.extensions.surf.util.URLDecoder; +import org.springframework.extensions.webscripts.Match; +import org.springframework.extensions.webscripts.RuntimeContainer; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.servlet.ServletAuthenticatorFactory; +import org.springframework.extensions.webscripts.servlet.WebScriptServletRuntime; + + +/** + * HTTP Servlet Web Script Runtime which can handle a tenant id in a web script path + * + * @author davidc + */ +public class TenantWebScriptServletRuntime extends WebScriptServletRuntime +{ + public TenantWebScriptServletRuntime(RuntimeContainer container, ServletAuthenticatorFactory authFactory, HttpServletRequest req, HttpServletResponse res, ServerProperties serverProperties) + { + super(container, authFactory, req, res, serverProperties); + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRuntime#getScriptUrl() + */ + @Override + protected String getScriptUrl() + { + // NOTE: Don't use req.getPathInfo() - it truncates the path at first semi-colon in Tomcat + final String requestURI = req.getRequestURI(); + final String serviceContextPath = req.getContextPath() + req.getServletPath(); + String pathInfo; + + if (serviceContextPath.length() > requestURI.length()) + { + // NOTE: assume a redirect has taken place e.g. tomcat welcome-page + // NOTE: this is unlikely, and we'll take the hit if the path contains a semi-colon + pathInfo = req.getPathInfo(); + } + else + { + pathInfo = URLDecoder.decode(requestURI.substring(serviceContextPath.length())); + } + + // ensure tenant is specified at beginning of path + // NOTE: must contain at least root / and single character for tenant name + if (pathInfo.length() < 2) + { + throw new WebScriptException("Missing tenant name in path: " + pathInfo); + } + // remove tenant + int idx = pathInfo.indexOf('/', 1); + pathInfo = pathInfo.substring(idx == -1 ? pathInfo.length() : idx); + return pathInfo; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptRuntime#createRequest(org.alfresco.web.scripts.WebScriptMatch) + */ + @Override + protected WebScriptRequest createRequest(Match match) + { + // TODO: construct org.springframework.extensions.webscripts.servlet.WebScriptServletResponse when + // org.alfresco.web.scripts.WebScriptServletResponse (deprecated) is removed + servletReq = new TenantWebScriptServletRequest(this, req, match, serverProperties); + return servletReq; + } + + /* (non-Javadoc) + * @see org.alfresco.web.scripts.WebScriptContainer#getName() + */ + public String getName() + { + return "TenantServletRuntime"; + } + +} diff --git a/source/java/org/alfresco/repo/web/scripts/invite/InviteByTicket.java b/source/java/org/alfresco/repo/web/scripts/invite/InviteByTicket.java index b0c91d179f..5d73fb1c30 100644 --- a/source/java/org/alfresco/repo/web/scripts/invite/InviteByTicket.java +++ b/source/java/org/alfresco/repo/web/scripts/invite/InviteByTicket.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -25,6 +25,8 @@ import org.alfresco.repo.invitation.site.InviteInfo; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.template.TemplateNode; import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; import org.alfresco.service.ServiceRegistry; import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.invitation.InvitationExceptionNotFound; @@ -102,14 +104,14 @@ public class InviteByTicket extends DeclarativeWebScript // run as system user String mtAwareSystemUser = tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain); - - Map ret = AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork>() + + Map ret = TenantUtil.runAsSystemTenant(new TenantRunAsWork>() { public Map doWork() throws Exception { return execute(req, status); } - }, mtAwareSystemUser); + }, tenantDomain); // authenticate as system for the rest of the webscript AuthenticationUtil.setRunAsUser(mtAwareSystemUser); diff --git a/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java b/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java index 3f5cdad445..864223b446 100644 --- a/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java +++ b/source/java/org/alfresco/repo/web/scripts/invite/InviteResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2005-2011 Alfresco Software Limited. + * Copyright (C) 2005-2013 Alfresco Software Limited. * * This file is part of Alfresco * @@ -23,6 +23,8 @@ import java.util.Map; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.tenant.TenantService; +import org.alfresco.repo.tenant.TenantUtil; +import org.alfresco.repo.tenant.TenantUtil.TenantRunAsWork; import org.alfresco.service.cmr.invitation.Invitation; import org.alfresco.service.cmr.invitation.InvitationExceptionForbidden; import org.alfresco.service.cmr.invitation.InvitationExceptionUserError; @@ -88,13 +90,13 @@ public class InviteResponse extends DeclarativeWebScript } // run as system user - return AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork>() + return TenantUtil.runAsSystemTenant(new TenantRunAsWork>() { public Map doWork() throws Exception { return execute(req, status); } - }, tenantService.getDomainUser(AuthenticationUtil.getSystemUserName(), tenantDomain)); + }, tenantDomain); } private Map execute(WebScriptRequest req, Status status) diff --git a/source/java/org/alfresco/repo/web/scripts/tenant/AbstractTenantAdminWebScript.java b/source/java/org/alfresco/repo/web/scripts/tenant/AbstractTenantAdminWebScript.java new file mode 100644 index 0000000000..25c33d54c2 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/tenant/AbstractTenantAdminWebScript.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.tenant; + +import org.alfresco.repo.tenant.TenantAdminService; +import org.springframework.extensions.webscripts.DeclarativeWebScript; + +/** + * @author janv + * @since 4.2 + */ +public abstract class AbstractTenantAdminWebScript extends DeclarativeWebScript +{ + protected static final String TENANT_DOMAIN = "tenantDomain"; + protected static final String TENANT_ADMIN_PASSWORD = "tenantAdminPassword"; + protected static final String TENANT_CONTENT_STORE_ROOT = "tenantContentStoreRoot"; + + protected TenantAdminService tenantAdminService; + + public void setTenantAdminService(TenantAdminService tenantAdminService) + { + this.tenantAdminService = tenantAdminService; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/tenant/TenantAdminSystemTest.java b/source/java/org/alfresco/repo/web/scripts/tenant/TenantAdminSystemTest.java new file mode 100644 index 0000000000..ffc1a40413 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/tenant/TenantAdminSystemTest.java @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.tenant; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; + +import junit.framework.TestCase; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONObject; +import org.springframework.extensions.surf.util.Base64; + +/** + * Simple test of Tenant REST API - eg. create tenant + * + * @author janv + * @since 4.2 + */ +public class TenantAdminSystemTest extends TestCase +{ + private static Log logger = LogFactory.getLog(TenantAdminSystemTest.class); + + // TODO - use test property file + private static final String REPO = "http://localhost:8080/alfresco"; + + // web script (REST) + private static final String WEBSCRIPT_ENDPOINT = REPO + "/service"; + + // Tenant Admin Service part-URLs + private static final String URL_TENANTS = "/api/tenants"; + + // Test users & passwords + private static final String ADMIN_USER = "admin"; + private static final String ADMIN_PW = "admin"; + + private static final String TENANT_PREFIX = "t"+System.currentTimeMillis()+"-"; + + private static final int T_CNT = 5; + + public enum Op {CREATE_TENANT}; + + public TenantAdminSystemTest() + { + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + } + + @Override + protected void tearDown() throws Exception + { + super.tearDown(); + } + + public void testLogin() throws Exception + { + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, ADMIN_USER, ADMIN_PW); + assertNotNull(ticket); + } + + public void testCreateTenants() throws Exception + { + runWorkers(1, T_CNT, Op.CREATE_TENANT); + } + + protected static void createTenant(String tenantDomain, String ticket) throws Exception + { + JSONObject tenant = new JSONObject(); + tenant.put("tenantDomain", tenantDomain); + tenant.put("tenantAdminPassword", tenantDomain); + + String url = WEBSCRIPT_ENDPOINT + URL_TENANTS; + String response = callPostWebScript(url, ticket, tenant.toString()); + + if (logger.isDebugEnabled()) + { + logger.debug("createTenant: " + tenantDomain); + logger.debug("----------"); + logger.debug(url); + logger.debug(response); + } + } + + public void testGetTenants() throws Exception + { + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, ADMIN_USER, ADMIN_PW); + + getTenants(ticket); + } + + protected void getTenants(String ticket) throws Exception + { + String url = WEBSCRIPT_ENDPOINT + URL_TENANTS; + String response = callGetWebScript(url, ticket); + + if (logger.isDebugEnabled()) + { + logger.debug("getTenants:"); + logger.debug("-------"); + logger.debug(url); + logger.debug(response); + } + } + + protected static String callGetWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + return callOutWebScript(urlString, "GET", ticket); + } + + protected static String callDeleteWebScript(String urlString, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + return callOutWebScript(urlString, "DELETE", ticket); + } + + protected static String callPostWebScript(String urlString, String ticket, String data) throws MalformedURLException, URISyntaxException, IOException + { + return callInOutWebScript(urlString, "POST", ticket, data); + } + + protected static String callPutWebScript(String urlString, String ticket, String data) throws MalformedURLException, URISyntaxException, IOException + { + return callInOutWebScript(urlString, "PUT", ticket, data); + } + + private static String callOutWebScript(String urlString, String method, String ticket) throws MalformedURLException, URISyntaxException, IOException + { + URL url = new URL(urlString); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod(method); + + if (ticket != null) + { + // add Base64 encoded authorization header + // refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication + conn.addRequestProperty("Authorization", "Basic " + Base64.encodeBytes(ticket.getBytes())); + } + + String result = null; + InputStream is = null; + BufferedReader br = null; + + try + { + is = conn.getInputStream(); + br = new BufferedReader(new InputStreamReader(is)); + + String line = null; + StringBuffer sb = new StringBuffer(); + while(((line = br.readLine()) !=null)) { + sb.append(line); + } + + result = sb.toString(); + } + finally + { + if (br != null) { br.close(); }; + if (is != null) { is.close(); }; + } + + return result; + } + + private static String callInOutWebScript(String urlString, String method, String ticket, String data) throws MalformedURLException, URISyntaxException, IOException + { + return callInOutWeb(urlString, method, ticket, data, "application/json", null); + } + + private static String callInOutWeb(String urlString, String method, String ticket, String data, String contentType, String soapAction) throws MalformedURLException, URISyntaxException, IOException + { + URL url = new URL(urlString); + + HttpURLConnection conn = (HttpURLConnection)url.openConnection(); + conn.setRequestMethod(method); + + conn.setRequestProperty("Content-type", contentType); + + conn.setDoOutput(true); + conn.setDoInput(true); + conn.setUseCaches (false); + + if (soapAction != null) + { + conn.setRequestProperty("SOAPAction", soapAction); + } + + if (ticket != null) + { + // add Base64 encoded authorization header + // refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication + conn.addRequestProperty("Authorization", "Basic " + Base64.encodeBytes(ticket.getBytes())); + } + + String result = null; + BufferedReader br = null; + DataOutputStream wr = null; + OutputStream os = null; + InputStream is = null; + + try + { + os = conn.getOutputStream(); + wr = new DataOutputStream(os); + wr.write(data.getBytes()); + wr.flush(); + } + finally + { + if (wr != null) { wr.close(); }; + if (os != null) { os.close(); }; + } + + try + { + is = conn.getInputStream(); + br = new BufferedReader(new InputStreamReader(is)); + + String line = null; + StringBuffer sb = new StringBuffer(); + while(((line = br.readLine()) !=null)) + { + sb.append(line); + } + + result = sb.toString(); + } + finally + { + if (br != null) { br.close(); }; + if (is != null) { is.close(); }; + } + + return result; + } + + protected static String callLoginWebScript(String serviceUrl, String username, String password) throws MalformedURLException, URISyntaxException, IOException + { + // Refer to: http://wiki.alfresco.com/wiki/Web_Scripts_Framework#HTTP_Basic_Authentication + String ticketResult = callGetWebScript(serviceUrl+"/api/login?u="+username+"&pw="+password, null); + + if (ticketResult != null) + { + int startTag = ticketResult.indexOf(""); + int endTag = ticketResult.indexOf(""); + if ((startTag != -1) && (endTag != -1)) + { + ticketResult = ticketResult.substring(startTag+("".length()), endTag); + } + } + + return ticketResult; + } + + private static void runWorkers(int threadCount, int threadBatch, Op mode) + { + logger.info("Start: Mode "+mode+" ["+threadCount+"]"); + + long start = System.currentTimeMillis(); + + Thread[] threads = new Thread[threadCount]; + + Worker[] nesters = new Worker[threadCount]; + + for (int i = 0; i < threadCount; i++) + { + int startId = (i*threadBatch)+1; + int endId = (i+1)*threadBatch; + + Worker nester = new Worker(mode, startId, endId); + nesters[i] = nester; + + threads[i] = new Thread(nester); + threads[i].start(); + } + + int totalCnt = 0; + long totalTime = 0; + + // join each thread so that we wait for them all to finish + for (int i = 0; i < threadCount; i++) + { + try + { + threads[i].join(); + + if (nesters[i].getErrorStackTrace() != null) + { + throw new RuntimeException(nesters[i].getErrorStackTrace()); + } + + if (nesters[i].getOpTime() != null) + { + totalTime = totalTime + nesters[i].getOpTime(); + totalCnt++; + } + } + catch (InterruptedException e) + { + // ignore + } + } + + logger.info("Finish: Mode "+mode+" [threadCount="+threadCount+", threadBatch="+threadBatch+"] in "+(System.currentTimeMillis()-start)+" ms (avg per thread = "+totalTime/totalCnt+" ms)"); + } + + private static class Worker implements Runnable + { + private Op op; + private int startId; + private int endId; + + private String errorStackTrace = null; + + private Long opTime; + + Worker(Op mode, int startId, int endId) + { + this.op = mode; + this.startId = startId; + this.endId = endId; + } + + public String getErrorStackTrace() + { + return errorStackTrace; + } + + public Long getOpTime() + { + return opTime; + } + + public void run() + { + String tenantDomain = null; + + try + { + long start = System.currentTimeMillis(); + + logger.info("Start: Mode "+op+" ("+startId+" to "+endId+") [ThreadId="+Thread.currentThread().getId()+"]"); + + for (int i = startId; i <= endId; i++) + { + tenantDomain = TENANT_PREFIX+String.format("%05d", i); + + switch(op) + { + case CREATE_TENANT: + String ticket = callLoginWebScript(WEBSCRIPT_ENDPOINT, ADMIN_USER, ADMIN_PW); + createTenant(TENANT_PREFIX+"--"+String.format("%05d", i), ticket); + break; + default: + throw new UnsupportedOperationException("Unsupported op type: "+op); + } + } + + opTime = (System.currentTimeMillis()-start); + + logger.info("Finish: Mode "+op+" ("+startId+" to "+endId+") [ThreadId="+Thread.currentThread().getId()+"] in "+opTime+" ms"); + } + catch (Throwable t) + { + logger.error("End " + tenantDomain + " with error " + t.getMessage()); + + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + + errorStackTrace = sw.toString(); + } + } + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/tenant/TenantDelete.java b/source/java/org/alfresco/repo/web/scripts/tenant/TenantDelete.java new file mode 100644 index 0000000000..3f3484446c --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/tenant/TenantDelete.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.tenant; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * REST API - delete tenant + * + * @author janv + * @since 4.2 + */ +public class TenantDelete extends AbstractTenantAdminWebScript +{ + protected static final Log logger = LogFactory.getLog(TenantPost.class); + + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + // get request parameters + Map templateVars = req.getServiceMatch().getTemplateVars(); + String tenantDomain = templateVars.get("tenantDomain"); + + tenantAdminService.deleteTenant(tenantDomain); + + Map model = new HashMap(0); + return model; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/tenant/TenantPost.java b/source/java/org/alfresco/repo/web/scripts/tenant/TenantPost.java new file mode 100644 index 0000000000..0c6fff64dc --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/tenant/TenantPost.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.tenant; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONTokener; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * REST API - create tenant + * + * @author janv + * @since 4.2 + */ +public class TenantPost extends AbstractTenantAdminWebScript +{ + protected static final Log logger = LogFactory.getLog(TenantPost.class); + + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + String tenantDomain = null; + String tenantAdminPassword = null; + String contentStoreRoot = null; + + try + { + JSONObject json = new JSONObject(new JSONTokener(req.getContent().getContent())); + + if (! json.has(TENANT_DOMAIN)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not find required 'tenantDomain' parameter"); + } + tenantDomain = json.getString(TENANT_DOMAIN); + + if (! json.has(TENANT_ADMIN_PASSWORD)) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not find required 'tenantAdminPassword' parameter"); + } + tenantAdminPassword = json.getString(TENANT_ADMIN_PASSWORD); + + if (json.has(TENANT_CONTENT_STORE_ROOT)) + { + contentStoreRoot = json.getString(TENANT_CONTENT_STORE_ROOT); + } + } + catch (IOException iox) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not read content from req.", iox); + } + catch (JSONException je) + { + throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Could not parse JSON from req.", je); + } + + tenantAdminService.createTenant(tenantDomain, tenantAdminPassword.toCharArray(), contentStoreRoot); + + Map model = new HashMap(0); + return model; + } +} diff --git a/source/java/org/alfresco/repo/web/scripts/tenant/TenantsGet.java b/source/java/org/alfresco/repo/web/scripts/tenant/TenantsGet.java new file mode 100644 index 0000000000..34376916b6 --- /dev/null +++ b/source/java/org/alfresco/repo/web/scripts/tenant/TenantsGet.java @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2005-2013 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.repo.web.scripts.tenant; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.alfresco.repo.tenant.Tenant; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptRequest; + +/** + * REST API - get tenants + * + * TODO filter params - eg. enabled/ disabled and name startsWith + * + * @author janv + * @since 4.2 + */ +public class TenantsGet extends AbstractTenantAdminWebScript +{ + protected static final Log logger = LogFactory.getLog(TenantsGet.class); + + @Override + protected Map executeImpl(WebScriptRequest req, Status status, Cache cache) + { + List tenants = tenantAdminService.getAllTenants(); + + Map model = new HashMap(1); + model.put("tenants", tenants); + + if (logger.isDebugEnabled()) + { + logger.debug("Result: \n\tRequest: " + req + "\n\tModel: " + model); + } + + return model; + } +} diff --git a/source/java/org/alfresco/slingshot/web/scripts/NodeBrowserScript.java b/source/java/org/alfresco/slingshot/web/scripts/NodeBrowserScript.java index 96eef9b48d..5b631ed188 100644 --- a/source/java/org/alfresco/slingshot/web/scripts/NodeBrowserScript.java +++ b/source/java/org/alfresco/slingshot/web/scripts/NodeBrowserScript.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2005-2011 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ package org.alfresco.slingshot.web.scripts; import java.io.IOException; @@ -54,6 +72,7 @@ public class NodeBrowserScript extends DeclarativeWebScript private static List queryLanguages = new ArrayList(); static { + queryLanguages.add("storeroot"); queryLanguages.add("noderef"); queryLanguages.add(SearchService.LANGUAGE_XPATH); queryLanguages.add(SearchService.LANGUAGE_LUCENE); @@ -459,8 +478,16 @@ public class NodeBrowserScript extends DeclarativeWebScript { public List execute() throws Throwable { - List searchResults = null; - if (queryLanguage.equals("noderef")) + List searchResults = null; + + if (queryLanguage.equals("storeroot")) + { + NodeRef rootNodeRef = getNodeService().getRootNode(storeRef); + searchResults = new ArrayList(1); + searchResults.add(new Node(rootNodeRef)); + return searchResults; + } + else if (queryLanguage.equals("noderef")) { // ensure node exists NodeRef nodeRef = new NodeRef(query);